customerio 1.0.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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