customerio 1.0.0 → 3.0.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,67 @@
1
+ require 'spec_helper'
2
+ require 'multi_json'
3
+ require 'base64'
4
+
5
+ describe Customerio::BaseClient do
6
+ let(:url) { "https://test.customer.io" }
7
+
8
+ let(:site_id) { "SITE_ID" }
9
+ let(:api_key) { "API_KEY" }
10
+ let(:track_client) { Customerio::BaseClient.new({ site_id: site_id, api_key: api_key }, { url: url }) }
11
+
12
+ let(:app_key) { "APP_KEY" }
13
+ let(:api_client) { Customerio::BaseClient.new({ app_key: app_key }, { url: url }) }
14
+
15
+ def api_uri(path)
16
+ "#{url}#{path}"
17
+ end
18
+
19
+ def track_client_request_headers
20
+ token = Base64.strict_encode64("#{site_id}:#{api_key}")
21
+ { 'Authorization': "Basic #{token}", 'Content-Type': 'application/json' }
22
+ end
23
+
24
+ def api_client_request_headers
25
+ { 'Authorization': "Bearer #{app_key}", 'Content-Type': 'application/json' }
26
+ end
27
+
28
+ describe "with a site ID and API key" do
29
+ it "uses the correct basic auth" do
30
+ stub_request(:put, api_uri('/some/path')).
31
+ with(headers: track_client_request_headers).
32
+ to_return(status: 200, body: "", headers: {})
33
+
34
+ track_client.request(:put, '/some/path', "")
35
+ end
36
+ end
37
+
38
+ describe "with an app key" do
39
+ it "uses the correct bearer token" do
40
+ stub_request(:put, api_uri('/some/path')).
41
+ with(headers: api_client_request_headers).
42
+ to_return(status: 200, body: "", headers: {})
43
+
44
+ api_client.request(:put, '/some/path', "")
45
+ end
46
+ end
47
+
48
+ describe "#verify_response" do
49
+ it "throws an error when the response isn't between 200 and 300" do
50
+ stub_request(:put, api_uri('/some/path')).
51
+ with(headers: api_client_request_headers).
52
+ to_return(status: 400, body: "", headers: {})
53
+
54
+ lambda { api_client.request_and_verify_response(:put, '/some/path', "") }.should(
55
+ raise_error(Customerio::InvalidResponse)
56
+ )
57
+ end
58
+
59
+ it "returns the response when the status is 200" do
60
+ stub_request(:put, api_uri('/some/path')).
61
+ with(headers: api_client_request_headers).
62
+ to_return(status: 200, body: "Test", headers: {})
63
+
64
+ api_client.request_and_verify_response(:put, '/some/path', "").body.should eq("Test")
65
+ end
66
+ end
67
+ end
@@ -1,39 +1,48 @@
1
1
  require 'spec_helper'
2
2
  require 'multi_json'
3
-
3
+ require 'base64'
4
4
 
5
5
  describe Customerio::Client do
6
- let(:client) { Customerio::Client.new("SITE_ID", "API_KEY", :json => false) }
7
- let(:response) { double("Response", :code => 200) }
6
+ let(:site_id) { "SITE_ID" }
7
+ let(:api_key) { "API_KEY" }
8
+
9
+ let(:client) { Customerio::Client.new(site_id, api_key) }
10
+ let(:response) { double("Response", code: 200) }
8
11
 
9
12
  def api_uri(path)
10
- "https://SITE_ID:API_KEY@track.customer.io#{path}"
13
+ "https://track.customer.io#{path}"
14
+ end
15
+
16
+ def request_headers
17
+ token = Base64.strict_encode64("#{site_id}:#{api_key}")
18
+ { 'Authorization': "Basic #{token}", 'Content-Type': 'application/json' }
11
19
  end
12
20
 
13
21
  def json(data)
14
22
  MultiJson.dump(data)
15
23
  end
16
24
 
17
- describe "json option" do
18
- let(:body) { { :id => 5, :name => "Bob" } }
25
+ it "uses json by default" do
26
+ body = { id: 5, name: "Bob" }
27
+ client = Customerio::Client.new("SITE_ID", "API_KEY")
19
28
 
20
- it "uses json by default" do
21
- client = Customerio::Client.new("SITE_ID", "API_KEY")
29
+ stub_request(:put, api_uri('/api/v1/customers/5')).
30
+ with(body: json(body),
31
+ headers: {'Content-Type'=>'application/json'}).
32
+ to_return(status: 200, body: "", headers: {})
22
33
 
23
- stub_request(:put, api_uri('/api/v1/customers/5')).
24
- with(:body => json(body),
25
- :headers => {'Content-Type'=>'application/json'}).
26
- to_return(:status => 200, :body => "", :headers => {})
34
+ client.identify(body)
35
+ end
27
36
 
28
- client.identify(body)
29
- end
37
+ describe "headers" do
38
+ let(:body) { { id: 1, token: :test } }
30
39
 
31
- it "allows disabling json" do
32
- client = Customerio::Client.new("SITE_ID", "API_KEY", :json => false)
40
+ it "sends the basic headers, base64 encoded with the request" do
41
+ client = Customerio::Client.new("SITE_ID", "API_KEY")
33
42
 
34
- stub_request(:put, api_uri('/api/v1/customers/5')).
35
- with(:body => { :id => "5", :name => "Bob" }).
36
- to_return(:status => 200, :body => "", :headers => {})
43
+ stub_request(:put, api_uri('/api/v1/customers/1')).
44
+ with(body: json(body), headers: request_headers).
45
+ to_return(status: 200, body: "", headers: {})
37
46
 
38
47
  client.identify(body)
39
48
  end
@@ -42,41 +51,54 @@ describe Customerio::Client do
42
51
  describe "#identify" do
43
52
  it "sends a PUT request to customer.io's customer API" do
44
53
  stub_request(:put, api_uri('/api/v1/customers/5')).
45
- with(:body => "id=5").
46
- to_return(:status => 200, :body => "", :headers => {})
54
+ with(body: json(id: "5")).
55
+ to_return(status: 200, body: "", headers: {})
56
+
57
+ client.identify(id: "5")
58
+ end
47
59
 
48
- client.identify(:id => 5)
60
+ it "escapes customer IDs" do
61
+ stub_request(:put, api_uri('/api/v1/customers/5%20')).
62
+ with(body: json({ id: "5 " })).
63
+ to_return(status: 200, body: "", headers: {})
64
+
65
+ client.identify(id: "5 ")
66
+
67
+ stub_request(:put, api_uri('/api/v1/customers/5%2F')).
68
+ with(body: { id: "5/" }).
69
+ to_return(status: 200, body: "", headers: {})
70
+ client.identify(id: "5/")
49
71
  end
50
72
 
51
73
  it "sends a PUT request to customer.io's customer API using json headers" do
52
- client = Customerio::Client.new("SITE_ID", "API_KEY", :json => true)
53
- body = { :id => 5, :name => "Bob" }
74
+ client = Customerio::Client.new("SITE_ID", "API_KEY", json: true)
75
+ body = { id: 5, name: "Bob" }
54
76
 
55
77
  stub_request(:put, api_uri('/api/v1/customers/5')).
56
- with(:body => json(body),
57
- :headers => {'Content-Type'=>'application/json'}).
58
- to_return(:status => 200, :body => "", :headers => {})
78
+ with(body: json(body),
79
+ headers: {'Content-Type'=>'application/json'}).
80
+ to_return(status: 200, body: "", headers: {})
59
81
 
60
82
  client.identify(body)
61
83
  end
62
84
 
63
85
  it "raises an error if PUT doesn't return a 2xx response code" do
64
86
  stub_request(:put, api_uri('/api/v1/customers/5')).
65
- with(:body => "id=5").
66
- to_return(:status => 500, :body => "", :headers => {})
87
+ with(body: json(id: 5)).
88
+ to_return(status: 500, body: "", headers: {})
67
89
 
68
- lambda { client.identify(:id => 5) }.should raise_error(Customerio::Client::InvalidResponse)
90
+ lambda { client.identify(id: 5) }.should raise_error(Customerio::InvalidResponse)
69
91
  end
70
92
 
71
93
  it "includes the HTTP response with raised errors" do
72
94
  stub_request(:put, api_uri('/api/v1/customers/5')).
73
- with(:body => "id=5").
74
- to_return(:status => 500, :body => "whatever", :headers => {})
95
+ with(body: json(id: 5)).
96
+ to_return(status: 500, body: "Server unavailable", headers: {})
75
97
 
76
- lambda { client.identify(:id => 5) }.should raise_error {|error|
77
- error.should be_a Customerio::Client::InvalidResponse
78
- error.response.code.should eq "500"
79
- error.response.body.should eq "whatever"
98
+ lambda { client.identify(id: 5) }.should raise_error {|error|
99
+ error.should be_a Customerio::InvalidResponse
100
+ error.code.should eq "500"
101
+ error.message.should eq "Server unavailable"
80
102
  }
81
103
  end
82
104
 
@@ -84,31 +106,32 @@ describe Customerio::Client do
84
106
  time = Time.now.to_i
85
107
 
86
108
  stub_request(:put, api_uri('/api/v1/customers/5')).with(
87
- :body => {
88
- :id => "5",
89
- :email => "customer@example.com",
90
- :created_at => time.to_s,
91
- :first_name => "Bob",
92
- :plan => "basic"
93
- }).to_return(:status => 200, :body => "", :headers => {})
109
+ body: json({
110
+ id: 5,
111
+ email: "customer@example.com",
112
+ created_at: time,
113
+ first_name: "Bob",
114
+ plan: "basic"
115
+ })).to_return(status: 200, body: "", headers: {})
94
116
 
95
117
  client.identify({
96
- :id => 5,
97
- :email => "customer@example.com",
98
- :created_at => time,
99
- :first_name => "Bob",
100
- :plan => "basic"
118
+ id: 5,
119
+ email: "customer@example.com",
120
+ created_at: time,
121
+ first_name: "Bob",
122
+ plan: "basic"
101
123
  })
102
124
  end
103
125
 
104
126
  it "requires an id attribute" do
105
- lambda { client.identify(:email => "customer@example.com") }.should raise_error(Customerio::Client::MissingIdAttributeError)
127
+ lambda { client.identify(email: "customer@example.com") }.should raise_error(Customerio::Client::MissingIdAttributeError)
128
+ lambda { client.identify(id: "") }.should raise_error(Customerio::Client::MissingIdAttributeError)
106
129
  end
107
130
 
108
131
  it 'should not raise errors when attribute keys are strings' do
109
132
  stub_request(:put, api_uri('/api/v1/customers/5')).
110
- with(:body => "id=5").
111
- to_return(:status => 200, :body => "", :headers => {})
133
+ with(body: json(id: 5)).
134
+ to_return(status: 200, body: "", headers: {})
112
135
 
113
136
  attributes = { "id" => 5 }
114
137
 
@@ -119,183 +142,237 @@ describe Customerio::Client do
119
142
  describe "#delete" do
120
143
  it "sends a DELETE request to the customer.io's event API" do
121
144
  stub_request(:delete, api_uri('/api/v1/customers/5')).
122
- to_return(:status => 200, :body => "", :headers => {})
145
+ to_return(status: 200, body: "", headers: {})
123
146
 
124
147
  client.delete(5)
125
148
  end
149
+
150
+ it "throws an error when customer_id is missing" do
151
+ stub_request(:put, /track.customer.io/)
152
+ .to_return(status: 200, body: "", headers: {})
153
+
154
+ lambda { client.delete(" ") }.should raise_error(Customerio::Client::ParamError, "customer_id must be a non-empty string")
155
+ end
156
+
157
+ it "escapes customer IDs" do
158
+ stub_request(:delete, api_uri('/api/v1/customers/5%20')).
159
+ to_return(status: 200, body: "", headers: {})
160
+
161
+ client.delete("5 ")
162
+ end
163
+ end
164
+
165
+ describe "#suppress" do
166
+ it "sends a POST request to the customer.io's suppress API" do
167
+ stub_request(:post, api_uri('/api/v1/customers/5/suppress')).
168
+ to_return(status: 200, body: "", headers: {})
169
+
170
+ client.suppress(5)
171
+ end
172
+
173
+ it "throws an error when customer_id is missing" do
174
+ stub_request(:put, /track.customer.io/)
175
+ .to_return(status: 200, body: "", headers: {})
176
+
177
+ lambda { client.suppress(" ") }.should raise_error(Customerio::Client::ParamError, "customer_id must be a non-empty string")
178
+ end
179
+ end
180
+
181
+ describe "#unsuppress" do
182
+ it "sends a POST request to the customer.io's unsuppress API" do
183
+ stub_request(:post, api_uri('/api/v1/customers/5/unsuppress')).
184
+ to_return(status: 200, body: "", headers: {})
185
+
186
+ client.unsuppress(5)
187
+ end
188
+
189
+ it "throws an error when customer_id is missing" do
190
+ stub_request(:put, /track.customer.io/)
191
+ .to_return(status: 200, body: "", headers: {})
192
+
193
+ lambda { client.suppress(" ") }.should raise_error(Customerio::Client::ParamError, "customer_id must be a non-empty string")
194
+ end
126
195
  end
127
196
 
128
197
  describe "#track" do
129
198
  it "raises an error if POST doesn't return a 2xx response code" do
130
199
  stub_request(:post, api_uri('/api/v1/customers/5/events')).
131
- with(:body => "name=purchase").
132
- to_return(:status => 500, :body => "", :headers => {})
200
+ with(body: json(name: "purchase", data: {})).
201
+ to_return(status: 500, body: "", headers: {})
133
202
 
134
- lambda { client.track(5, "purchase") }.should raise_error(Customerio::Client::InvalidResponse)
203
+ lambda { client.track(5, "purchase") }.should raise_error(Customerio::InvalidResponse)
204
+ end
205
+
206
+ it "throws an error when customer_id or event_name is missing" do
207
+ stub_request(:put, /track.customer.io/)
208
+ .to_return(status: 200, body: "", headers: {})
209
+
210
+ lambda { client.track(" ", "test_event") }.should raise_error(Customerio::Client::ParamError, "customer_id must be a non-empty string")
211
+ lambda { client.track(5, " ") }.should raise_error(Customerio::Client::ParamError, "event_name must be a non-empty string")
135
212
  end
136
213
 
137
214
  it "uses the site_id and api key for basic auth and sends the event name" do
138
215
  stub_request(:post, api_uri('/api/v1/customers/5/events')).
139
- with(:body => "name=purchase").
140
- to_return(:status => 200, :body => "", :headers => {})
216
+ with(body: json(name: "purchase", data: {})).
217
+ to_return(status: 200, body: "", headers: {})
141
218
 
142
219
  client.track(5, "purchase")
143
220
  end
144
221
 
145
222
  it "sends any optional event attributes" do
146
223
  stub_request(:post, api_uri('/api/v1/customers/5/events')).
147
- with(:body => {
148
- :name => "purchase",
149
- :data => {
150
- :type => "socks",
151
- :price => "13.99"
224
+ with(body: json({
225
+ name: "purchase",
226
+ data: {
227
+ type: "socks",
228
+ price: "13.99"
152
229
  }
153
- }).
154
- to_return(:status => 200, :body => "", :headers => {})
230
+ })).
231
+ to_return(status: 200, body: "", headers: {})
155
232
 
156
- client.track(5, "purchase", :type => "socks", :price => "13.99")
233
+ client.track(5, "purchase", type: "socks", price: "13.99")
157
234
  end
158
235
 
159
236
  it "copes with arrays" do
160
237
  stub_request(:post, api_uri('/api/v1/customers/5/events')).
161
- with(:body => {
162
- :name => "event",
163
- :data => {
164
- :things => ["a", "b", "c"]
238
+ with(body: {
239
+ name: "event",
240
+ data: {
241
+ things: ["a", "b", "c"]
165
242
  }
166
243
  }).
167
- to_return(:status => 200, :body => "", :headers => {})
244
+ to_return(status: 200, body: "", headers: {})
168
245
 
169
- client.track(5, "event", :things => ["a", "b", "c"])
246
+ client.track(5, "event", things: ["a", "b", "c"])
170
247
  end
171
248
 
172
249
  it "copes with hashes" do
173
250
  stub_request(:post, api_uri('/api/v1/customers/5/events')).
174
- with(:body => {
175
- :name => "event",
176
- :data => {
177
- :stuff => { :a => "b" }
251
+ with(body: {
252
+ name: "event",
253
+ data: {
254
+ stuff: { a: "b" }
178
255
  }
179
256
  }).
180
- to_return(:status => 200, :body => "", :headers => {})
257
+ to_return(status: 200, body: "", headers: {})
181
258
 
182
- client.track(5, "event", :stuff => { :a => "b" })
259
+ client.track(5, "event", stuff: { a: "b" })
183
260
  end
184
261
 
185
262
  it "sends a POST request as json using json headers" do
186
- client = Customerio::Client.new("SITE_ID", "API_KEY", :json => true)
187
- data = { :type => "socks", :price => "13.99" }
188
- body = { :name => "purchase", :data => data }
263
+ client = Customerio::Client.new("SITE_ID", "API_KEY", json: true)
264
+ data = { type: "socks", price: "13.99" }
265
+ body = { name: "purchase", data: data }
189
266
 
190
267
  stub_request(:post, api_uri('/api/v1/customers/5/events')).
191
- with(:body => json(body),
192
- :headers => {'Content-Type'=>'application/json'}).
193
- to_return(:status => 200, :body => "", :headers => {})
268
+ with(body: json(body),
269
+ headers: {'Content-Type'=>'application/json'}).
270
+ to_return(status: 200, body: "", headers: {})
194
271
 
195
272
  client.track(5, "purchase", data)
196
273
  end
197
274
 
198
275
  it "allows sending of a timestamp" do
199
276
  stub_request(:post, api_uri('/api/v1/customers/5/events')).
200
- with(:body => {
201
- :name => "purchase",
202
- :data => {
203
- :type => "socks",
204
- :price => "13.99",
205
- :timestamp => "1561231234"
277
+ with(body: json({
278
+ name: "purchase",
279
+ data: {
280
+ type: "socks",
281
+ price: "13.99",
282
+ timestamp: 1561231234
206
283
  },
207
- :timestamp => "1561231234"
208
- }).
209
- to_return(:status => 200, :body => "", :headers => {})
284
+ timestamp: 1561231234
285
+ })).
286
+ to_return(status: 200, body: "", headers: {})
210
287
 
211
- client.track(5, "purchase", :type => "socks", :price => "13.99", :timestamp => 1561231234)
288
+ client.track(5, "purchase", type: "socks", price: "13.99", timestamp: 1561231234)
212
289
  end
213
290
 
214
291
  it "doesn't send timestamp if timestamp is in milliseconds" do
215
292
  stub_request(:post, api_uri('/api/v1/customers/5/events')).
216
- with(:body => {
217
- :name => "purchase",
218
- :data => {
219
- :type => "socks",
220
- :price => "13.99",
221
- :timestamp => "1561231234000"
293
+ with(body: json({
294
+ name: "purchase",
295
+ data: {
296
+ type: "socks",
297
+ price: "13.99",
298
+ timestamp: 1561231234000
222
299
  }
223
- }).
224
- to_return(:status => 200, :body => "", :headers => {})
300
+ })).
301
+ to_return(status: 200, body: "", headers: {})
225
302
 
226
- client.track(5, "purchase", :type => "socks", :price => "13.99", :timestamp => 1561231234000)
303
+ client.track(5, "purchase", type: "socks", price: "13.99", timestamp: 1561231234000)
227
304
  end
228
305
 
229
306
  it "doesn't send timestamp if timestamp is a date" do
230
307
  date = Time.now
231
308
 
232
309
  stub_request(:post, api_uri('/api/v1/customers/5/events')).
233
- with(:body => {
234
- :name => "purchase",
235
- :data => {
236
- :type => "socks",
237
- :price => "13.99",
238
- :timestamp => Time.now.to_s
310
+ with(body: {
311
+ name: "purchase",
312
+ data: {
313
+ type: "socks",
314
+ price: "13.99",
315
+ timestamp: Time.now.to_s
239
316
  }
240
317
  }).
241
- to_return(:status => 200, :body => "", :headers => {})
318
+ to_return(status: 200, body: "", headers: {})
242
319
 
243
- client.track(5, "purchase", :type => "socks", :price => "13.99", :timestamp => date)
320
+ client.track(5, "purchase", type: "socks", price: "13.99", timestamp: date)
244
321
  end
245
322
 
246
323
  it "doesn't send timestamp if timestamp isn't an integer" do
247
324
  stub_request(:post, api_uri('/api/v1/customers/5/events')).
248
- with(:body => {
249
- :name => "purchase",
250
- :data => {
251
- :type => "socks",
252
- :price => "13.99",
253
- :timestamp => "Hello world"
325
+ with(body: json({
326
+ name: "purchase",
327
+ data: {
328
+ type: "socks",
329
+ price: "13.99",
330
+ timestamp: "Hello world"
254
331
  }
255
- }).
332
+ })).
256
333
 
257
- to_return(:status => 200, :body => "", :headers => {})
334
+ to_return(status: 200, body: "", headers: {})
258
335
 
259
- client.track(5, "purchase", :type => "socks", :price => "13.99", :timestamp => "Hello world")
336
+ client.track(5, "purchase", type: "socks", price: "13.99", timestamp: "Hello world")
260
337
  end
261
338
 
262
339
  context "tracking an anonymous event" do
263
340
  it "sends a POST request to the customer.io's anonymous event API" do
264
341
  stub_request(:post, api_uri('/api/v1/events')).
265
- with(:body => "name=purchase").
266
- to_return(:status => 200, :body => "", :headers => {})
342
+ with(body: json({ name: "purchase", data: {} })).
343
+ to_return(status: 200, body: "", headers: {})
267
344
 
268
- client.track("purchase")
345
+ client.anonymous_track("purchase")
269
346
  end
270
347
 
271
348
  it "sends any optional event attributes" do
272
349
  stub_request(:post, api_uri('/api/v1/events')).
273
- with(:body => {
274
- :name => "purchase",
275
- :data => {
276
- :type => "socks",
277
- :price => "13.99"
350
+ with(body: json({
351
+ name: "purchase",
352
+ data: {
353
+ type: "socks",
354
+ price: "13.99"
278
355
  }
279
- }).
280
- to_return(:status => 200, :body => "", :headers => {})
356
+ })).
357
+ to_return(status: 200, body: "", headers: {})
281
358
 
282
- client.track("purchase", :type => "socks", :price => "13.99")
359
+ client.anonymous_track("purchase", type: "socks", price: "13.99")
283
360
  end
284
361
 
285
362
  it "allows sending of a timestamp" do
286
363
  stub_request(:post, api_uri('/api/v1/events')).
287
- with(:body => {
288
- :name => "purchase",
289
- :data => {
290
- :type => "socks",
291
- :price => "13.99",
292
- :timestamp => "1561231234"
364
+ with(body: json({
365
+ name: "purchase",
366
+ data: {
367
+ type: "socks",
368
+ price: "13.99",
369
+ timestamp: 1561231234
293
370
  },
294
- :timestamp => "1561231234"
295
- }).
296
- to_return(:status => 200, :body => "", :headers => {})
371
+ timestamp: 1561231234
372
+ })).
373
+ to_return(status: 200, body: "", headers: {})
297
374
 
298
- client.track("purchase", :type => "socks", :price => "13.99", :timestamp => 1561231234)
375
+ client.anonymous_track("purchase", type: "socks", price: "13.99", timestamp: 1561231234)
299
376
  end
300
377
  end
301
378
  end
@@ -303,56 +380,126 @@ describe Customerio::Client do
303
380
  describe "#anonymous_track" do
304
381
  it "raises an error if POST doesn't return a 2xx response code" do
305
382
  stub_request(:post, api_uri('/api/v1/events')).
306
- with(:body => "name=purchase").
307
- to_return(:status => 500, :body => "", :headers => {})
383
+ with(body: json(name: "purchase", data: {})).
384
+ to_return(status: 500, body: "", headers: {})
385
+
386
+ lambda { client.anonymous_track("purchase") }.should raise_error(Customerio::InvalidResponse)
387
+ end
388
+
389
+ it "throws an error when event_name is missing" do
390
+ stub_request(:put, /track.customer.io/)
391
+ .to_return(status: 200, body: "", headers: {})
308
392
 
309
- lambda { client.anonymous_track("purchase") }.should raise_error(Customerio::Client::InvalidResponse)
393
+ lambda { client.anonymous_track(" ") }.should raise_error(Customerio::Client::ParamError, "event_name must be a non-empty string")
310
394
  end
311
395
 
312
396
  it "uses the site_id and api key for basic auth and sends the event name" do
313
397
  stub_request(:post, api_uri('/api/v1/events')).
314
- with(:body => "name=purchase").
315
- to_return(:status => 200, :body => "", :headers => {})
398
+ with(body: json(name: "purchase", data: {})).
399
+ to_return(status: 200, body: "", headers: {})
316
400
 
317
401
  client.anonymous_track("purchase")
318
402
  end
319
403
 
320
404
  it "sends any optional event attributes" do
321
405
  stub_request(:post, api_uri('/api/v1/events')).
322
- with(:body => {
323
- :name => "purchase",
324
- :data => {
325
- :type => "socks",
326
- :price => "27.99"
406
+ with(body: {
407
+ name: "purchase",
408
+ data: {
409
+ type: "socks",
410
+ price: "27.99"
327
411
  },
328
412
  }).
329
413
 
330
- to_return(:status => 200, :body => "", :headers => {})
414
+ to_return(status: 200, body: "", headers: {})
331
415
 
332
- client.anonymous_track("purchase", :type => "socks", :price => "27.99")
416
+ client.anonymous_track("purchase", type: "socks", price: "27.99")
333
417
  end
334
418
 
335
419
  it "allows sending of a timestamp" do
336
420
  stub_request(:post, api_uri('/api/v1/events')).
337
- with(:body => {
338
- :name => "purchase",
339
- :data => {
340
- :type => "socks",
341
- :price => "27.99",
342
- :timestamp => "1561235678"
421
+ with(body: json({
422
+ name: "purchase",
423
+ data: {
424
+ type: "socks",
425
+ price: "27.99",
426
+ timestamp: 1561235678
343
427
  },
344
- :timestamp => "1561235678"
345
- }).
428
+ timestamp: 1561235678
429
+ })).
346
430
 
347
- to_return(:status => 200, :body => "", :headers => {})
431
+ to_return(status: 200, body: "", headers: {})
348
432
 
349
- client.anonymous_track("purchase", :type => "socks", :price => "27.99", :timestamp => 1561235678)
433
+ client.anonymous_track("purchase", type: "socks", price: "27.99", timestamp: 1561235678)
350
434
  end
351
435
 
352
436
  context "too many arguments are passed" do
353
437
  it "throws an error" do
354
- lambda { client.anonymous_track("purchase", "text", :type => "socks", :price => "27.99") }.should raise_error(ArgumentError)
438
+ lambda { client.anonymous_track("purchase", "text", type: "socks", price: "27.99") }.should raise_error(ArgumentError)
355
439
  end
356
440
  end
357
441
  end
442
+
443
+ describe "#devices" do
444
+ it "allows for the creation of a new device" do
445
+ stub_request(:put, api_uri('/api/v1/customers/5/devices')).
446
+ to_return(status: 200, body: "", headers: {})
447
+
448
+ client.add_device(5, "androidDeviceID", "ios", {last_used: 1561235678})
449
+ client.add_device(5, "iosDeviceID", "android")
450
+ end
451
+ it "requires a valid customer_id when creating" do
452
+ stub_request(:put, api_uri('/api/v1/customers/5/devices')).
453
+ to_return(status: 200, body: "", headers: {})
454
+
455
+ lambda { client.add_device("", "ios", "myDeviceID") }.should raise_error(Customerio::Client::ParamError)
456
+ lambda { client.add_device(nil, "ios", "myDeviceID", {last_used: 1561235678}) }.should raise_error(Customerio::Client::ParamError)
457
+ end
458
+ it "requires a valid token when creating" do
459
+ stub_request(:put, api_uri('/api/v1/customers/5/devices')).
460
+ to_return(status: 200, body: "", headers: {})
461
+
462
+ lambda { client.add_device(5, "", "ios") }.should raise_error(Customerio::Client::ParamError)
463
+ lambda { client.add_device(5, nil, "ios", {last_used: 1561235678}) }.should raise_error(Customerio::Client::ParamError)
464
+ end
465
+ it "requires a valid platform when creating" do
466
+ stub_request(:put, api_uri('/api/v1/customers/5/devices')).
467
+ to_return(status: 200, body: "", headers: {})
468
+
469
+ lambda { client.add_device(5, "token", "") }.should raise_error(Customerio::Client::ParamError)
470
+ lambda { client.add_device(5, "toke", nil, {last_used: 1561235678}) }.should raise_error(Customerio::Client::ParamError)
471
+ end
472
+ it "accepts a nil data param" do
473
+ stub_request(:put, api_uri('/api/v1/customers/5/devices')).
474
+ to_return(status: 200, body: "", headers: {})
475
+
476
+ client.add_device(5, "ios", "myDeviceID", nil)
477
+ end
478
+ it "fails on invalid data param" do
479
+ stub_request(:put, api_uri('/api/v1/customers/5/devices')).
480
+ to_return(status: 200, body: "", headers: {})
481
+
482
+ lambda { client.add_device(5, "ios", "myDeviceID", 1000) }.should raise_error(Customerio::Client::ParamError)
483
+ end
484
+ it "supports deletion of devices by token" do
485
+ stub_request(:delete, api_uri('/api/v1/customers/5/devices/myDeviceID')).
486
+ to_return(status: 200, body: "", headers: {})
487
+
488
+ client.delete_device(5, "myDeviceID")
489
+ end
490
+ it "requires a valid customer_id when deleting" do
491
+ stub_request(:delete, api_uri('/api/v1/customers/5/devices/myDeviceID')).
492
+ to_return(status: 200, body: "", headers: {})
493
+
494
+ lambda { client.delete_device("", "myDeviceID") }.should raise_error(Customerio::Client::ParamError)
495
+ lambda { client.delete_device(nil, "myDeviceID") }.should raise_error(Customerio::Client::ParamError)
496
+ end
497
+ it "requires a valid device_id when deleting" do
498
+ stub_request(:delete, api_uri('/api/v1/customers/5/devices/myDeviceID')).
499
+ to_return(status: 200, body: "", headers: {})
500
+
501
+ lambda { client.delete_device(5, "") }.should raise_error(Customerio::Client::ParamError)
502
+ lambda { client.delete_device(5, nil) }.should raise_error(Customerio::Client::ParamError)
503
+ end
504
+ end
358
505
  end