customerio 3.1.0 → 4.2.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.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +1 -1
- data/CHANGELOG.markdown +14 -0
- data/README.md +25 -2
- data/customerio.gemspec +1 -1
- data/lib/customerio/base_client.rb +2 -0
- data/lib/customerio/client.rb +67 -6
- data/lib/customerio/version.rb +1 -1
- data/spec/api_client_spec.rb +1 -1
- data/spec/base_client_spec.rb +2 -2
- data/spec/client_spec.rb +144 -67
- metadata +8 -9
- data/.circleci/config.yml +0 -61
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e58bba756887e5c3ae6e7aa75b3e2c5bd08fc5733d45ee513b56895e35b58011
|
4
|
+
data.tar.gz: 912374a003fe636fc5837cbf030a64141218f83b63fb9e455efa033375a2a8bb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1529f5cc20959ce9cdbe9e4103a29f5b5205594727b8951be18d61a6851520741e52150b20b20603b7d890f62ab56c3d391d9503d6c21e99a31032085da06557
|
7
|
+
data.tar.gz: '08adc273fd1d1cf2df0453788ac9c8889b8576aadf865cd9d587f029fe4de4a05b35d61dbcd845da2fdbba81b056bd7d3b92a9d7d2a3ad8800a3ad6b87ecb313'
|
data/.github/workflows/main.yml
CHANGED
data/CHANGELOG.markdown
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
## Customerio 4.1.0 - Sep 27, 2021
|
2
|
+
### Added
|
3
|
+
- Added support for [merge customers](https://customer.io/docs/api/#operation/merge) API
|
4
|
+
|
5
|
+
## Customerio 4.0.1 - July 13, 2021
|
6
|
+
### Changed
|
7
|
+
- Update addressable gem dependency to v2.8.0
|
8
|
+
|
9
|
+
## Customerio 4.0.0 - July 6, 2021
|
10
|
+
### Removed
|
11
|
+
- The `anonymous_track` method.
|
12
|
+
|
13
|
+
### Added
|
14
|
+
- The `track_anonymous` method replaces `anonymous_track`. This method requires an `anonymous_id` parameter and will no longer trigger campaigns. If you previously used anonymous events to trigger campaigns, you can still do so [directly through the API](https://customer.io/docs/api/#operation/trackAnonymous). We now refer to anonymous events that trigger campaigns as ["invite events"](https://customer.io/docs/anonymous-events/#anonymous-or-invite).
|
1
15
|
|
2
16
|
## Customerio 3.1.0 - March 25, 2021
|
3
17
|
### Added
|
data/README.md
CHANGED
@@ -104,6 +104,21 @@ recreated.
|
|
104
104
|
$customerio.delete(5)
|
105
105
|
```
|
106
106
|
|
107
|
+
### Merge duplicate customer profiles
|
108
|
+
|
109
|
+
When you merge two people, you pick a primary person and merge a secondary, duplicate person into it. The primary person remains after the merge and the secondary is deleted. This process is permanent: you cannot recover the secondary person.
|
110
|
+
|
111
|
+
The first and third parameters represent the identifier for the primary and secondary people respectively—one of `id`, `email`, or `cio_id`. The second and fourth parameters are the identifier values for the primary and secondary people respectively.
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
# $customerio.merge_customers("primaryType", "primaryIdentifier", "secondaryType", "secondaryIdentifier")
|
115
|
+
# primaryType / secondaryType are one of "id", "email", or "cio_id"
|
116
|
+
# primaryIdentifier / secondaryIdentifier are the identifier value corresponding to the type.
|
117
|
+
|
118
|
+
# merge customer "cperson@gmail.com" into "cool.person@company.com"
|
119
|
+
$customerio.merge_customers("email", "cool.person@company.com", "email", "cperson@gmail.com")
|
120
|
+
```
|
121
|
+
|
107
122
|
### Tracking a custom event
|
108
123
|
|
109
124
|
Now that you're identifying your customers with [Customer.io](http://customer.io), you can now send events like
|
@@ -131,10 +146,18 @@ $customerio.track(5, "purchase", :type => "socks", :price => "13.99", :timestamp
|
|
131
146
|
|
132
147
|
### Tracking anonymous events
|
133
148
|
|
134
|
-
You can also send anonymous events, for situations where you don't yet have a customer record
|
149
|
+
You can also send anonymous events, for situations where you don't yet have a customer record yet. An anonymous event requires an `anonymous_id` representing the unknown person and an event `name`. When you identify a person, you can set their `anonymous_id` attribute. If [event merging](https://customer.io/docs/anonymous-events/#turn-on-merging) is turned on in your workspace, and the attribute matches the `anonymous_id` in one or more events that were logged within the last 30 days, we associate those events with the person.
|
150
|
+
|
151
|
+
Anonymous events cannot trigger campaigns by themselves. To trigger a campaign, the anonymous event must be associated with a person within 72 hours of the `track_anonymous` request.
|
135
152
|
|
136
153
|
```ruby
|
137
|
-
|
154
|
+
# Arguments
|
155
|
+
# anonymous_id (required) - the id representing the unknown person.
|
156
|
+
# name (required) - the name of the event you want to track.
|
157
|
+
# attributes (optional) - any related information you want to attach to the
|
158
|
+
# event.
|
159
|
+
|
160
|
+
$customerio.track_anonymous(anonymous_id, "product_view", :type => "socks" )
|
138
161
|
```
|
139
162
|
|
140
163
|
Use the `recipient` attribute to specify the email address to send the messages to. [See our documentation on how to use anonymous events for more details](https://learn.customer.io/recipes/invite-emails.html).
|
data/customerio.gemspec
CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |gem|
|
|
17
17
|
gem.version = Customerio::VERSION
|
18
18
|
|
19
19
|
gem.add_dependency('multi_json', "~> 1.0")
|
20
|
-
gem.add_dependency('addressable', '~> 2.
|
20
|
+
gem.add_dependency('addressable', '~> 2.8.0')
|
21
21
|
|
22
22
|
gem.add_development_dependency('rake', '~> 10.5')
|
23
23
|
gem.add_development_dependency('rspec', '3.3.0')
|
@@ -44,6 +44,8 @@ module Customerio
|
|
44
44
|
|
45
45
|
req = request_class(method).new(uri.path)
|
46
46
|
|
47
|
+
headers['User-Agent'] = "Customer.io Ruby Client/" + Customerio::VERSION
|
48
|
+
|
47
49
|
if @auth.has_key?(:site_id) && @auth.has_key?(:api_key)
|
48
50
|
req.initialize_http_header(headers)
|
49
51
|
req.basic_auth @auth[:site_id], @auth[:api_key]
|
data/lib/customerio/client.rb
CHANGED
@@ -1,7 +1,19 @@
|
|
1
1
|
require "addressable/uri"
|
2
2
|
|
3
3
|
module Customerio
|
4
|
+
class IdentifierType
|
5
|
+
ID = "id"
|
6
|
+
EMAIL = "email"
|
7
|
+
CIOID = "cio_id"
|
8
|
+
end
|
9
|
+
|
4
10
|
class Client
|
11
|
+
PUSH_OPENED = 'opened'
|
12
|
+
PUSH_CONVERTED = 'converted'
|
13
|
+
PUSH_DELIVERED = 'delivered'
|
14
|
+
|
15
|
+
VALID_PUSH_EVENTS = [PUSH_OPENED, PUSH_CONVERTED, PUSH_DELIVERED]
|
16
|
+
|
5
17
|
class MissingIdAttributeError < RuntimeError; end
|
6
18
|
class ParamError < RuntimeError; end
|
7
19
|
|
@@ -39,9 +51,11 @@ module Customerio
|
|
39
51
|
create_customer_event(customer_id, event_name, attributes)
|
40
52
|
end
|
41
53
|
|
42
|
-
def
|
54
|
+
def track_anonymous(anonymous_id, event_name, attributes = {})
|
55
|
+
raise ParamError.new("anonymous_id must be a non-empty string") if is_empty?(anonymous_id)
|
43
56
|
raise ParamError.new("event_name must be a non-empty string") if is_empty?(event_name)
|
44
|
-
|
57
|
+
|
58
|
+
create_anonymous_event(anonymous_id, event_name, attributes)
|
45
59
|
end
|
46
60
|
|
47
61
|
def add_device(customer_id, device_id, platform, data={})
|
@@ -70,6 +84,30 @@ module Customerio
|
|
70
84
|
@client.request_and_verify_response(:delete, device_id_path(customer_id, device_id))
|
71
85
|
end
|
72
86
|
|
87
|
+
def track_push_notification_event(event_name, attributes = {})
|
88
|
+
keys = [:delivery_id, :device_id, :timestamp]
|
89
|
+
attributes = Hash[attributes.map { |(k,v)| [ k.to_sym, v ] }].
|
90
|
+
select { |k, v| keys.include?(k) }
|
91
|
+
|
92
|
+
raise ParamError.new('event_name must be one of opened, converted, or delivered') unless VALID_PUSH_EVENTS.include?(event_name)
|
93
|
+
raise ParamError.new('delivery_id must be a non-empty string') unless attributes[:delivery_id] != "" and !attributes[:delivery_id].nil?
|
94
|
+
raise ParamError.new('device_id must be a non-empty string') unless attributes[:device_id] != "" and !attributes[:device_id].nil?
|
95
|
+
raise ParamError.new('timestamp must be a valid timestamp') unless valid_timestamp?(attributes[:timestamp])
|
96
|
+
|
97
|
+
@client.request_and_verify_response(:post, track_push_notification_event_path, attributes.merge(event: event_name))
|
98
|
+
end
|
99
|
+
|
100
|
+
def merge_customers(primary_id_type, primary_id, secondary_id_type, secondary_id)
|
101
|
+
raise ParamError.new("invalid primary_id_type") if !is_valid_id_type?(primary_id_type)
|
102
|
+
raise ParamError.new("primary_id must be a non-empty string") if is_empty?(primary_id)
|
103
|
+
raise ParamError.new("invalid secondary_id_type") if !is_valid_id_type?(secondary_id_type)
|
104
|
+
raise ParamError.new("secondary_id must be a non-empty string") if is_empty?(secondary_id)
|
105
|
+
|
106
|
+
body = { :primary => {primary_id_type => primary_id}, :secondary => {secondary_id_type => secondary_id} }
|
107
|
+
|
108
|
+
@client.request_and_verify_response(:post, merge_customers_path, body)
|
109
|
+
end
|
110
|
+
|
73
111
|
private
|
74
112
|
|
75
113
|
def escape(val)
|
@@ -97,6 +135,14 @@ module Customerio
|
|
97
135
|
"/api/v1/customers/#{escape(customer_id)}/unsuppress"
|
98
136
|
end
|
99
137
|
|
138
|
+
def track_push_notification_event_path
|
139
|
+
"/push/events"
|
140
|
+
end
|
141
|
+
|
142
|
+
def merge_customers_path
|
143
|
+
"/api/v1/merge_customers"
|
144
|
+
end
|
145
|
+
|
100
146
|
def create_or_update(attributes = {})
|
101
147
|
attributes = Hash[attributes.map { |(k,v)| [ k.to_sym, v ] }]
|
102
148
|
raise MissingIdAttributeError.new("Must provide a customer id") if is_empty?(attributes[:id])
|
@@ -106,16 +152,27 @@ module Customerio
|
|
106
152
|
end
|
107
153
|
|
108
154
|
def create_customer_event(customer_id, event_name, attributes = {})
|
109
|
-
create_event(
|
155
|
+
create_event(
|
156
|
+
url: "#{customer_path(customer_id)}/events",
|
157
|
+
event_name: event_name,
|
158
|
+
attributes: attributes
|
159
|
+
)
|
110
160
|
end
|
111
161
|
|
112
|
-
def create_anonymous_event(event_name, attributes = {})
|
113
|
-
create_event(
|
162
|
+
def create_anonymous_event(anonymous_id, event_name, attributes = {})
|
163
|
+
create_event(
|
164
|
+
url: "/api/v1/events",
|
165
|
+
event_name: event_name,
|
166
|
+
anonymous_id: anonymous_id,
|
167
|
+
attributes: attributes
|
168
|
+
)
|
114
169
|
end
|
115
170
|
|
116
|
-
def create_event(url
|
171
|
+
def create_event(url:, event_name:, anonymous_id: nil, attributes: {})
|
117
172
|
body = { :name => event_name, :data => attributes }
|
118
173
|
body[:timestamp] = attributes[:timestamp] if valid_timestamp?(attributes[:timestamp])
|
174
|
+
body[:anonymous_id] = anonymous_id unless anonymous_id.nil?
|
175
|
+
|
119
176
|
@client.request_and_verify_response(:post, url, body)
|
120
177
|
end
|
121
178
|
|
@@ -126,5 +183,9 @@ module Customerio
|
|
126
183
|
def is_empty?(val)
|
127
184
|
val.nil? || (val.is_a?(String) && val.strip == "")
|
128
185
|
end
|
186
|
+
|
187
|
+
def is_valid_id_type?(input)
|
188
|
+
[IdentifierType::ID, IdentifierType::CIOID, IdentifierType::EMAIL].include? input
|
189
|
+
end
|
129
190
|
end
|
130
191
|
end
|
data/lib/customerio/version.rb
CHANGED
data/spec/api_client_spec.rb
CHANGED
@@ -14,7 +14,7 @@ describe Customerio::APIClient do
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def request_headers
|
17
|
-
{ 'Authorization': "Bearer #{app_key}", 'Content-Type': 'application/json' }
|
17
|
+
{ 'Authorization': "Bearer #{app_key}", 'Content-Type': 'application/json', 'User-Agent': 'Customer.io Ruby Client/' + Customerio::VERSION }
|
18
18
|
end
|
19
19
|
|
20
20
|
def json(data)
|
data/spec/base_client_spec.rb
CHANGED
@@ -18,11 +18,11 @@ describe Customerio::BaseClient do
|
|
18
18
|
|
19
19
|
def track_client_request_headers
|
20
20
|
token = Base64.strict_encode64("#{site_id}:#{api_key}")
|
21
|
-
{ 'Authorization': "Basic #{token}", 'Content-Type': 'application/json' }
|
21
|
+
{ 'Authorization': "Basic #{token}", 'Content-Type': 'application/json', 'User-Agent': 'Customer.io Ruby Client/' + Customerio::VERSION }
|
22
22
|
end
|
23
23
|
|
24
24
|
def api_client_request_headers
|
25
|
-
{ 'Authorization': "Bearer #{app_key}", 'Content-Type': 'application/json' }
|
25
|
+
{ 'Authorization': "Bearer #{app_key}", 'Content-Type': 'application/json', 'User-Agent': 'Customer.io Ruby Client/' + Customerio::VERSION }
|
26
26
|
end
|
27
27
|
|
28
28
|
describe "with a site ID and API key" do
|
data/spec/client_spec.rb
CHANGED
@@ -150,16 +150,18 @@ describe Customerio::Client do
|
|
150
150
|
time = Time.now.to_i
|
151
151
|
|
152
152
|
stub_request(:put, api_uri('/api/v1/customers/5')).with(
|
153
|
-
body:
|
153
|
+
body: {
|
154
154
|
id: 5,
|
155
155
|
email: "customer@example.com",
|
156
156
|
created_at: time,
|
157
157
|
first_name: "Bob",
|
158
|
-
plan: "basic"
|
159
|
-
|
158
|
+
plan: "basic",
|
159
|
+
anonymous_id: "anon-id"
|
160
|
+
}).to_return(status: 200, body: "", headers: {})
|
160
161
|
|
161
162
|
client.identify({
|
162
163
|
id: 5,
|
164
|
+
anonymous_id: "anon-id",
|
163
165
|
email: "customer@example.com",
|
164
166
|
created_at: time,
|
165
167
|
first_name: "Bob",
|
@@ -381,31 +383,35 @@ describe Customerio::Client do
|
|
381
383
|
end
|
382
384
|
|
383
385
|
context "tracking an anonymous event" do
|
386
|
+
let(:anon_id) { "anon-id" }
|
387
|
+
|
384
388
|
it "sends a POST request to the customer.io's anonymous event API" do
|
385
389
|
stub_request(:post, api_uri('/api/v1/events')).
|
386
|
-
with(body:
|
390
|
+
with(body: { anonymous_id: anon_id, name: "purchase", data: {} }).
|
387
391
|
to_return(status: 200, body: "", headers: {})
|
388
392
|
|
389
|
-
client.
|
393
|
+
client.track_anonymous(anon_id, "purchase")
|
390
394
|
end
|
391
395
|
|
392
396
|
it "sends any optional event attributes" do
|
393
397
|
stub_request(:post, api_uri('/api/v1/events')).
|
394
|
-
with(body:
|
398
|
+
with(body: {
|
399
|
+
anonymous_id: anon_id,
|
395
400
|
name: "purchase",
|
396
401
|
data: {
|
397
402
|
type: "socks",
|
398
403
|
price: "13.99"
|
399
404
|
}
|
400
|
-
})
|
405
|
+
}).
|
401
406
|
to_return(status: 200, body: "", headers: {})
|
402
407
|
|
403
|
-
client.
|
408
|
+
client.track_anonymous(anon_id, "purchase", type: "socks", price: "13.99")
|
404
409
|
end
|
405
410
|
|
406
411
|
it "allows sending of a timestamp" do
|
407
412
|
stub_request(:post, api_uri('/api/v1/events')).
|
408
|
-
with(body:
|
413
|
+
with(body: {
|
414
|
+
anonymous_id: anon_id,
|
409
415
|
name: "purchase",
|
410
416
|
data: {
|
411
417
|
type: "socks",
|
@@ -413,73 +419,34 @@ describe Customerio::Client do
|
|
413
419
|
timestamp: 1561231234
|
414
420
|
},
|
415
421
|
timestamp: 1561231234
|
416
|
-
})
|
422
|
+
}).
|
417
423
|
to_return(status: 200, body: "", headers: {})
|
418
424
|
|
419
|
-
client.
|
425
|
+
client.track_anonymous(anon_id, "purchase", type: "socks", price: "13.99", timestamp: 1561231234)
|
420
426
|
end
|
421
|
-
end
|
422
|
-
end
|
423
|
-
|
424
|
-
describe "#anonymous_track" do
|
425
|
-
it "raises an error if POST doesn't return a 2xx response code" do
|
426
|
-
stub_request(:post, api_uri('/api/v1/events')).
|
427
|
-
with(body: json(name: "purchase", data: {})).
|
428
|
-
to_return(status: 500, body: "", headers: {})
|
429
|
-
|
430
|
-
lambda { client.anonymous_track("purchase") }.should raise_error(Customerio::InvalidResponse)
|
431
|
-
end
|
432
|
-
|
433
|
-
it "throws an error when event_name is missing" do
|
434
|
-
stub_request(:put, /track.customer.io/)
|
435
|
-
.to_return(status: 200, body: "", headers: {})
|
436
|
-
|
437
|
-
lambda { client.anonymous_track(" ") }.should raise_error(Customerio::Client::ParamError, "event_name must be a non-empty string")
|
438
|
-
end
|
439
|
-
|
440
|
-
it "uses the site_id and api key for basic auth and sends the event name" do
|
441
|
-
stub_request(:post, api_uri('/api/v1/events')).
|
442
|
-
with(body: json(name: "purchase", data: {})).
|
443
|
-
to_return(status: 200, body: "", headers: {})
|
444
|
-
|
445
|
-
client.anonymous_track("purchase")
|
446
|
-
end
|
447
|
-
|
448
|
-
it "sends any optional event attributes" do
|
449
|
-
stub_request(:post, api_uri('/api/v1/events')).
|
450
|
-
with(body: {
|
451
|
-
name: "purchase",
|
452
|
-
data: {
|
453
|
-
type: "socks",
|
454
|
-
price: "27.99"
|
455
|
-
},
|
456
|
-
}).
|
457
427
|
|
458
|
-
|
428
|
+
it "raises an error if POST doesn't return a 2xx response code" do
|
429
|
+
stub_request(:post, api_uri('/api/v1/events')).
|
430
|
+
with(body: { anonymous_id: anon_id, name: "purchase", data: {} }).
|
431
|
+
to_return(status: 500, body: "", headers: {})
|
459
432
|
|
460
|
-
|
461
|
-
|
433
|
+
lambda { client.track_anonymous(anon_id, "purchase") }.should raise_error(Customerio::InvalidResponse)
|
434
|
+
end
|
462
435
|
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
data: {
|
468
|
-
type: "socks",
|
469
|
-
price: "27.99",
|
470
|
-
timestamp: 1561235678
|
471
|
-
},
|
472
|
-
timestamp: 1561235678
|
473
|
-
})).
|
436
|
+
it "throws an error when anonymous_id is missing" do
|
437
|
+
stub_request(:post, api_uri('/api/v1/events')).
|
438
|
+
with(body: { anonymous_id: anon_id, name: "purchase", data: {} }).
|
439
|
+
to_return(status: 500, body: "", headers: {})
|
474
440
|
|
475
|
-
|
441
|
+
lambda { client.track_anonymous("", "some_event") }.should raise_error(Customerio::Client::ParamError)
|
442
|
+
end
|
476
443
|
|
477
|
-
|
478
|
-
|
444
|
+
it "throws an error when event_name is missing" do
|
445
|
+
stub_request(:post, api_uri('/api/v1/events')).
|
446
|
+
with(body: { anonymous_id: anon_id, name: "purchase", data: {} }).
|
447
|
+
to_return(status: 500, body: "", headers: {})
|
479
448
|
|
480
|
-
|
481
|
-
it "throws an error" do
|
482
|
-
lambda { client.anonymous_track("purchase", "text", type: "socks", price: "27.99") }.should raise_error(ArgumentError)
|
449
|
+
lambda { client.track_anonymous(anon_id, "") }.should raise_error(Customerio::Client::ParamError)
|
483
450
|
end
|
484
451
|
end
|
485
452
|
end
|
@@ -546,4 +513,114 @@ describe Customerio::Client do
|
|
546
513
|
lambda { client.delete_device(5, nil) }.should raise_error(Customerio::Client::ParamError)
|
547
514
|
end
|
548
515
|
end
|
516
|
+
|
517
|
+
describe "#track_push_notification_event" do
|
518
|
+
attr_accessor :client, :attributes
|
519
|
+
|
520
|
+
before(:each) do
|
521
|
+
@client = Customerio::Client.new("SITE_ID", "API_KEY", :json => true)
|
522
|
+
@attributes = {
|
523
|
+
:delivery_id => 'foo',
|
524
|
+
:device_id => 'bar',
|
525
|
+
:timestamp => Time.now.to_i
|
526
|
+
}
|
527
|
+
end
|
528
|
+
|
529
|
+
it "sends a POST request to customer.io's /push/events endpoint" do
|
530
|
+
stub_request(:post, api_uri('/push/events')).
|
531
|
+
with(
|
532
|
+
:body => json(attributes.merge({
|
533
|
+
:event => 'opened'
|
534
|
+
})),
|
535
|
+
:headers => {
|
536
|
+
'Content-Type' => 'application/json'
|
537
|
+
}).
|
538
|
+
to_return(:status => 200, :body => "", :headers => {})
|
539
|
+
|
540
|
+
client.track_push_notification_event('opened', attributes)
|
541
|
+
end
|
542
|
+
|
543
|
+
it "should raise if event is invalid" do
|
544
|
+
stub_request(:post, api_uri('/push/events')).
|
545
|
+
to_return(:status => 200, :body => "", :headers => {})
|
546
|
+
|
547
|
+
expect {
|
548
|
+
client.track_push_notification_event('closed', attributes.merge({ :delivery_id => nil }))
|
549
|
+
}.to raise_error(Customerio::Client::ParamError, 'event_name must be one of opened, converted, or delivered')
|
550
|
+
end
|
551
|
+
|
552
|
+
it "should raise if delivery_id is invalid" do
|
553
|
+
stub_request(:post, api_uri('/push/events')).
|
554
|
+
to_return(:status => 200, :body => "", :headers => {})
|
555
|
+
|
556
|
+
expect {
|
557
|
+
client.track_push_notification_event('opened', attributes.merge({ :delivery_id => nil }))
|
558
|
+
}.to raise_error(Customerio::Client::ParamError, 'delivery_id must be a non-empty string')
|
559
|
+
|
560
|
+
expect {
|
561
|
+
client.track_push_notification_event('opened', attributes.merge({ :delivery_id => '' }))
|
562
|
+
}.to raise_error(Customerio::Client::ParamError, 'delivery_id must be a non-empty string')
|
563
|
+
end
|
564
|
+
|
565
|
+
it "should raise if device_id is invalid" do
|
566
|
+
stub_request(:post, api_uri('/push/events')).
|
567
|
+
to_return(:status => 200, :body => "", :headers => {})
|
568
|
+
|
569
|
+
expect {
|
570
|
+
client.track_push_notification_event('opened', attributes.merge({ :device_id => nil }))
|
571
|
+
}.to raise_error(Customerio::Client::ParamError, 'device_id must be a non-empty string')
|
572
|
+
|
573
|
+
expect {
|
574
|
+
client.track_push_notification_event('opened', attributes.merge({ :device_id => '' }))
|
575
|
+
}.to raise_error(Customerio::Client::ParamError, 'device_id must be a non-empty string')
|
576
|
+
end
|
577
|
+
|
578
|
+
it "should raise if timestamp is invalid" do
|
579
|
+
stub_request(:post, api_uri('/push/events')).
|
580
|
+
to_return(:status => 200, :body => "", :headers => {})
|
581
|
+
|
582
|
+
expect {
|
583
|
+
client.track_push_notification_event('opened', attributes.merge({ :timestamp => nil }))
|
584
|
+
}.to raise_error(Customerio::Client::ParamError, 'timestamp must be a valid timestamp')
|
585
|
+
|
586
|
+
expect {
|
587
|
+
client.track_push_notification_event('opened', attributes.merge({ :timestamp => 999999999 }))
|
588
|
+
}.to raise_error(Customerio::Client::ParamError, 'timestamp must be a valid timestamp')
|
589
|
+
|
590
|
+
expect {
|
591
|
+
client.track_push_notification_event('opened', attributes.merge({ :timestamp => 100000000000 }))
|
592
|
+
}.to raise_error(Customerio::Client::ParamError, 'timestamp must be a valid timestamp')
|
593
|
+
end
|
594
|
+
end
|
595
|
+
|
596
|
+
describe "#merge_customers" do
|
597
|
+
before(:each) do
|
598
|
+
@client = Customerio::Client.new("SITE_ID", "API_KEY", :json => true)
|
599
|
+
end
|
600
|
+
|
601
|
+
it "should raise validation errors on merge params" do
|
602
|
+
expect {
|
603
|
+
client.merge_customers("", "id1", Customerio::IdentifierType::ID, "id2")
|
604
|
+
}.to raise_error(Customerio::Client::ParamError, 'invalid primary_id_type')
|
605
|
+
|
606
|
+
expect {
|
607
|
+
client.merge_customers(Customerio::IdentifierType::EMAIL, "", Customerio::IdentifierType::ID, "id2")
|
608
|
+
}.to raise_error(Customerio::Client::ParamError, 'primary_id must be a non-empty string')
|
609
|
+
|
610
|
+
expect {
|
611
|
+
client.merge_customers(Customerio::IdentifierType::CIOID, "id1", "", "id2")
|
612
|
+
}.to raise_error(Customerio::Client::ParamError, 'invalid secondary_id_type')
|
613
|
+
|
614
|
+
expect {
|
615
|
+
client.merge_customers(Customerio::IdentifierType::ID, "id1", Customerio::IdentifierType::ID, "")
|
616
|
+
}.to raise_error(Customerio::Client::ParamError, 'secondary_id must be a non-empty string')
|
617
|
+
end
|
618
|
+
|
619
|
+
it "requires a valid customer_id when creating" do
|
620
|
+
stub_request(:post, api_uri('/api/v1/merge_customers')).
|
621
|
+
to_return(status: 200, body: "", headers: {})
|
622
|
+
|
623
|
+
client.merge_customers(Customerio::IdentifierType::ID, "ID1", Customerio::IdentifierType::EMAIL, "hello@company.com")
|
624
|
+
end
|
625
|
+
end
|
549
626
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: customerio
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Allison
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-10-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: multi_json
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 2.
|
33
|
+
version: 2.8.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 2.
|
40
|
+
version: 2.8.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -101,7 +101,6 @@ executables: []
|
|
101
101
|
extensions: []
|
102
102
|
extra_rdoc_files: []
|
103
103
|
files:
|
104
|
-
- ".circleci/config.yml"
|
105
104
|
- ".github/workflows/main.yml"
|
106
105
|
- ".gitignore"
|
107
106
|
- CHANGELOG.markdown
|
@@ -126,7 +125,7 @@ homepage: http://customer.io
|
|
126
125
|
licenses:
|
127
126
|
- MIT
|
128
127
|
metadata: {}
|
129
|
-
post_install_message:
|
128
|
+
post_install_message:
|
130
129
|
rdoc_options: []
|
131
130
|
require_paths:
|
132
131
|
- lib
|
@@ -141,8 +140,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
141
140
|
- !ruby/object:Gem::Version
|
142
141
|
version: '0'
|
143
142
|
requirements: []
|
144
|
-
rubygems_version: 3.
|
145
|
-
signing_key:
|
143
|
+
rubygems_version: 3.0.3
|
144
|
+
signing_key:
|
146
145
|
specification_version: 4
|
147
146
|
summary: A ruby client for the Customer.io event API.
|
148
147
|
test_files:
|
data/.circleci/config.yml
DELETED
@@ -1,61 +0,0 @@
|
|
1
|
-
---
|
2
|
-
version: 2
|
3
|
-
|
4
|
-
references:
|
5
|
-
restore_cache: &restore_cache
|
6
|
-
type: cache-restore
|
7
|
-
name: Restore bundle cache
|
8
|
-
key: customerio-ruby-{{ checksum "customerio.gemspec" }}
|
9
|
-
|
10
|
-
save_cache: &save_cache
|
11
|
-
type: cache-save
|
12
|
-
name: Store bundle cache
|
13
|
-
key: customerio-ruby-{{ checksum "customerio.gemspec" }}
|
14
|
-
paths:
|
15
|
-
- vendor/bundle
|
16
|
-
|
17
|
-
jobs:
|
18
|
-
ruby_27:
|
19
|
-
working_directory: ~/customerio-ruby
|
20
|
-
docker:
|
21
|
-
- image: circleci/ruby:2.7.2
|
22
|
-
environment:
|
23
|
-
RAILS_ENV: test
|
24
|
-
steps:
|
25
|
-
- checkout
|
26
|
-
- *restore_cache
|
27
|
-
- run: bundle install
|
28
|
-
- *save_cache
|
29
|
-
- run: bundle exec rspec
|
30
|
-
ruby_26:
|
31
|
-
working_directory: ~/customerio-ruby
|
32
|
-
docker:
|
33
|
-
- image: circleci/ruby:2.6.6
|
34
|
-
environment:
|
35
|
-
RAILS_ENV: test
|
36
|
-
steps:
|
37
|
-
- checkout
|
38
|
-
- *restore_cache
|
39
|
-
- run: bundle install
|
40
|
-
- *save_cache
|
41
|
-
- run: bundle exec rspec
|
42
|
-
ruby_25:
|
43
|
-
working_directory: ~/customerio-ruby
|
44
|
-
docker:
|
45
|
-
- image: circleci/ruby:2.5.8
|
46
|
-
environment:
|
47
|
-
RAILS_ENV: test
|
48
|
-
steps:
|
49
|
-
- checkout
|
50
|
-
- *restore_cache
|
51
|
-
- run: bundle install
|
52
|
-
- *save_cache
|
53
|
-
- run: bundle exec rspec
|
54
|
-
|
55
|
-
workflows:
|
56
|
-
version: 2
|
57
|
-
test:
|
58
|
-
jobs:
|
59
|
-
- ruby_27
|
60
|
-
- ruby_26
|
61
|
-
- ruby_25
|