drip-ruby 3.2.0 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +5 -1
- data/.rubocop_todo.yml +17 -9
- data/.travis.yml +1 -1
- data/CHANGELOG.md +20 -1
- data/Gemfile +10 -0
- data/drip-ruby.gemspec +3 -11
- data/lib/drip/client.rb +44 -66
- data/lib/drip/client/accounts.rb +2 -2
- data/lib/drip/client/broadcasts.rb +2 -2
- data/lib/drip/client/campaign_subscriptions.rb +1 -1
- data/lib/drip/client/campaigns.rb +5 -5
- data/lib/drip/client/configuration.rb +28 -0
- data/lib/drip/client/conversions.rb +2 -2
- data/lib/drip/client/custom_fields.rb +1 -1
- data/lib/drip/client/events.rb +4 -4
- data/lib/drip/client/forms.rb +2 -2
- data/lib/drip/client/http_client.rb +64 -0
- data/lib/drip/client/orders.rb +3 -3
- data/lib/drip/client/shopper_activity.rb +78 -0
- data/lib/drip/client/subscribers.rb +13 -13
- data/lib/drip/client/tags.rb +3 -3
- data/lib/drip/client/webhooks.rb +5 -5
- data/lib/drip/client/workflow_triggers.rb +3 -3
- data/lib/drip/client/workflows.rb +6 -6
- data/lib/drip/request.rb +31 -0
- data/lib/drip/response.rb +13 -13
- data/lib/drip/version.rb +1 -1
- data/test/drip/client/configuration_test.rb +122 -0
- data/test/drip/client/http_client_test.rb +96 -0
- data/test/drip/client/shopper_activity_test.rb +175 -0
- data/test/drip/client_test.rb +32 -97
- data/test/drip/collection_test.rb +14 -0
- data/test/drip/collections/account_test.rb +8 -0
- data/test/drip/collections/broadcasts_test.rb +8 -0
- data/test/drip/collections/campaign_subscriptions_test.rb +8 -0
- data/test/drip/collections/campaigns_test.rb +8 -0
- data/test/drip/collections/errors_test.rb +8 -0
- data/test/drip/collections/orders_test.rb +8 -0
- data/test/drip/collections/purchases_test.rb +8 -0
- data/test/drip/collections/tags_test.rb +8 -0
- data/test/drip/collections/webhooks_test.rb +8 -0
- data/test/drip/collections/workflow_triggers_test.rb +8 -0
- data/test/drip/collections/workflows_test.rb +8 -0
- data/test/drip/request_test.rb +58 -0
- data/test/drip/resource_test.rb +12 -0
- data/test/drip/resources/tag_test.rb +13 -0
- data/test/drip/response_test.rb +33 -0
- data/test/test_helper.rb +3 -0
- metadata +42 -104
data/lib/drip/request.rb
ADDED
@@ -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
|
data/lib/drip/response.rb
CHANGED
@@ -44,20 +44,20 @@ module Drip
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def parse_members
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
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
|
-
|
60
|
-
end
|
60
|
+
members[key] = klass.new(value)
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|
data/lib/drip/version.rb
CHANGED
@@ -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
|