intercom 3.9.5 → 4.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +406 -236
  3. data/Rakefile +1 -1
  4. data/changes.txt +32 -0
  5. data/lib/intercom/api_operations/archive.rb +2 -1
  6. data/lib/intercom/api_operations/delete.rb +16 -0
  7. data/lib/intercom/api_operations/find.rb +5 -2
  8. data/lib/intercom/api_operations/find_all.rb +4 -3
  9. data/lib/intercom/api_operations/list.rb +4 -1
  10. data/lib/intercom/api_operations/load.rb +4 -2
  11. data/lib/intercom/api_operations/nested_resource.rb +70 -0
  12. data/lib/intercom/api_operations/save.rb +6 -4
  13. data/lib/intercom/api_operations/scroll.rb +4 -5
  14. data/lib/intercom/api_operations/search.rb +3 -2
  15. data/lib/intercom/article.rb +7 -0
  16. data/lib/intercom/base_collection_proxy.rb +73 -0
  17. data/lib/intercom/client.rb +36 -25
  18. data/lib/intercom/client_collection_proxy.rb +17 -39
  19. data/lib/intercom/collection.rb +7 -0
  20. data/lib/intercom/company.rb +8 -0
  21. data/lib/intercom/contact.rb +22 -3
  22. data/lib/intercom/conversation.rb +5 -0
  23. data/lib/intercom/data_attribute.rb +7 -0
  24. data/lib/intercom/deprecated_leads_collection_proxy.rb +22 -0
  25. data/lib/intercom/deprecated_resources.rb +13 -0
  26. data/lib/intercom/errors.rb +3 -0
  27. data/lib/intercom/extended_api_operations/segments.rb +3 -1
  28. data/lib/intercom/extended_api_operations/tags.rb +3 -1
  29. data/lib/intercom/lead.rb +21 -0
  30. data/lib/intercom/lib/dynamic_accessors.rb +9 -10
  31. data/lib/intercom/lib/typed_json_deserializer.rb +42 -37
  32. data/lib/intercom/note.rb +4 -0
  33. data/lib/intercom/request.rb +37 -33
  34. data/lib/intercom/scroll_collection_proxy.rb +38 -42
  35. data/lib/intercom/search_collection_proxy.rb +30 -65
  36. data/lib/intercom/section.rb +23 -0
  37. data/lib/intercom/segment.rb +4 -0
  38. data/lib/intercom/service/article.rb +20 -0
  39. data/lib/intercom/service/base_service.rb +7 -0
  40. data/lib/intercom/service/collection.rb +24 -0
  41. data/lib/intercom/service/company.rb +2 -12
  42. data/lib/intercom/service/contact.rb +31 -10
  43. data/lib/intercom/service/conversation.rb +12 -3
  44. data/lib/intercom/service/data_attribute.rb +20 -0
  45. data/lib/intercom/service/lead.rb +41 -0
  46. data/lib/intercom/service/note.rb +4 -8
  47. data/lib/intercom/service/section.rb +7 -0
  48. data/lib/intercom/service/subscription.rb +2 -2
  49. data/lib/intercom/service/tag.rb +9 -9
  50. data/lib/intercom/service/visitor.rb +17 -8
  51. data/lib/intercom/tag.rb +4 -0
  52. data/lib/intercom/traits/api_resource.rb +44 -18
  53. data/lib/intercom/traits/dirty_tracking.rb +8 -1
  54. data/lib/intercom/user.rb +12 -3
  55. data/lib/intercom/utils.rb +13 -2
  56. data/lib/intercom/version.rb +1 -1
  57. data/lib/intercom/visitor.rb +0 -2
  58. data/lib/intercom.rb +33 -22
  59. data/spec/spec_helper.rb +843 -520
  60. data/spec/unit/intercom/admin_spec.rb +2 -2
  61. data/spec/unit/intercom/article_spec.rb +40 -0
  62. data/spec/unit/intercom/base_collection_proxy_spec.rb +47 -0
  63. data/spec/unit/intercom/client_collection_proxy_spec.rb +41 -41
  64. data/spec/unit/intercom/client_spec.rb +25 -26
  65. data/spec/unit/intercom/collection_spec.rb +32 -0
  66. data/spec/unit/intercom/company_spec.rb +18 -14
  67. data/spec/unit/intercom/contact_spec.rb +385 -33
  68. data/spec/unit/intercom/conversation_spec.rb +55 -7
  69. data/spec/unit/intercom/count_spec.rb +4 -4
  70. data/spec/unit/intercom/data_attribute_spec.rb +40 -0
  71. data/spec/unit/intercom/deprecated_leads_collection_proxy_spec.rb +17 -0
  72. data/spec/unit/intercom/event_spec.rb +9 -11
  73. data/spec/unit/intercom/job_spec.rb +24 -24
  74. data/spec/unit/intercom/lead_spec.rb +57 -0
  75. data/spec/unit/intercom/lib/flat_store_spec.rb +22 -20
  76. data/spec/unit/intercom/message_spec.rb +1 -1
  77. data/spec/unit/intercom/note_spec.rb +4 -10
  78. data/spec/unit/intercom/request_spec.rb +1 -1
  79. data/spec/unit/intercom/scroll_collection_proxy_spec.rb +40 -39
  80. data/spec/unit/intercom/search_collection_proxy_spec.rb +32 -28
  81. data/spec/unit/intercom/section_spec.rb +32 -0
  82. data/spec/unit/intercom/segment_spec.rb +2 -2
  83. data/spec/unit/intercom/subscription_spec.rb +5 -6
  84. data/spec/unit/intercom/tag_spec.rb +22 -14
  85. data/spec/unit/intercom/team_spec.rb +2 -2
  86. data/spec/unit/intercom/traits/api_resource_spec.rb +107 -52
  87. data/spec/unit/intercom/user_spec.rb +224 -226
  88. data/spec/unit/intercom/visitor_spec.rb +49 -0
  89. data/spec/unit/intercom_spec.rb +5 -3
  90. metadata +34 -8
  91. data/lib/intercom/customer.rb +0 -10
  92. data/lib/intercom/service/customer.rb +0 -14
  93. data/spec/unit/intercom/visitors_spec.rb +0 -61
@@ -1,59 +1,411 @@
1
- require "spec_helper"
1
+ # frozen_string_literal: true
2
2
 
3
- describe "Intercom::Contact" do
4
- let (:client) { Intercom::Client.new(app_id: 'app_id', api_key: 'api_key') }
3
+ require 'spec_helper'
4
+
5
+ describe Intercom::Contact do
6
+ let(:client) { Intercom::Client.new(token: 'token') }
5
7
 
6
8
  it 'should be listable' do
7
9
  proxy = client.contacts.all
8
- proxy.resource_name.must_equal 'contacts'
9
- proxy.finder_url.must_equal '/contacts'
10
- proxy.resource_class.must_equal Intercom::Contact
10
+ _(proxy.resource_name).must_equal 'contacts'
11
+ _(proxy.url).must_equal '/contacts'
12
+ _(proxy.resource_class).must_equal Intercom::Contact
11
13
  end
12
14
 
13
- it 'should not throw ArgumentErrors when there are no parameters' do
14
- client.expects(:post)
15
- client.contacts.create
15
+ it 'should throw an ArgumentError when there are no parameters' do
16
+ _(proc { client.contacts.create }).must_raise(ArgumentError)
16
17
  end
17
18
 
18
- it 'can update a contact with an id' do
19
- contact = Intercom::Contact.new(:id => "de45ae78gae1289cb")
20
- client.expects(:put).with("/contacts/de45ae78gae1289cb", {'custom_attributes' => {}})
19
+ it "to_hash'es itself" do
20
+ created_at = Time.now
21
+ contact = Intercom::Contact.new(email: 'jim@example.com', contact_id: '12345', created_at: created_at, name: 'Jim Bob')
22
+ as_hash = contact.to_hash
23
+ _(as_hash['email']).must_equal 'jim@example.com'
24
+ _(as_hash['contact_id']).must_equal '12345'
25
+ _(as_hash['created_at']).must_equal created_at.to_i
26
+ _(as_hash['name']).must_equal 'Jim Bob'
27
+ end
28
+
29
+ it 'presents created_at and last_impression_at as Date' do
30
+ now = Time.now
31
+ contact = Intercom::Contact.new(created_at: now, last_impression_at: now)
32
+ _(contact.created_at).must_be_kind_of Time
33
+ _(contact.created_at.to_s).must_equal now.to_s
34
+ _(contact.last_impression_at).must_be_kind_of Time
35
+ _(contact.last_impression_at.to_s).must_equal now.to_s
36
+ end
37
+
38
+ it 'is throws a Intercom::AttributeNotSetError on trying to access an attribute that has not been set' do
39
+ contact = Intercom::Contact.new
40
+ _(proc { contact.foo_property }).must_raise Intercom::AttributeNotSetError
41
+ end
42
+
43
+ it 'presents a complete contact record correctly' do
44
+ contact = Intercom::Contact.new(test_contact)
45
+ _(contact.external_id).must_equal 'id-from-customers-app'
46
+ _(contact.email).must_equal 'bob@example.com'
47
+ _(contact.name).must_equal 'Joe Schmoe'
48
+ _(contact.workspace_id).must_equal 'the-workspace-id'
49
+ _(contact.session_count).must_equal 123
50
+ _(contact.created_at.to_i).must_equal 1_401_970_114
51
+ _(contact.remote_created_at.to_i).must_equal 1_393_613_864
52
+ _(contact.updated_at.to_i).must_equal 1_401_970_114
53
+
54
+ _(contact.avatar).must_be_kind_of Intercom::Avatar
55
+ _(contact.avatar.image_url).must_equal 'https://graph.facebook.com/1/picture?width=24&height=24'
56
+
57
+ _(contact.notes).must_be_kind_of Intercom::BaseCollectionProxy
58
+ _(contact.tags).must_be_kind_of Intercom::BaseCollectionProxy
59
+ _(contact.companies).must_be_kind_of Intercom::ClientCollectionProxy
60
+
61
+ _(contact.custom_attributes).must_be_kind_of Intercom::Lib::FlatStore
62
+ _(contact.custom_attributes['a']).must_equal 'b'
63
+ _(contact.custom_attributes['b']).must_equal 2
64
+
65
+ _(contact.social_profiles.size).must_equal 4
66
+ twitter_account = contact.social_profiles.first
67
+ _(twitter_account).must_be_kind_of Intercom::SocialProfile
68
+ _(twitter_account.name).must_equal 'twitter'
69
+ _(twitter_account.username).must_equal 'abc'
70
+ _(twitter_account.url).must_equal 'http://twitter.com/abc'
71
+
72
+ _(contact.location_data).must_be_kind_of Intercom::LocationData
73
+ _(contact.location_data.city_name).must_equal 'Dublin'
74
+ _(contact.location_data.continent_code).must_equal 'EU'
75
+ _(contact.location_data.country_name).must_equal 'Ireland'
76
+ _(contact.location_data.latitude).must_equal '90'
77
+ _(contact.location_data.longitude).must_equal '10'
78
+ _(contact.location_data.country_code).must_equal 'IRL'
79
+
80
+ _(contact.unsubscribed_from_emails).must_equal true
81
+ _(contact.user_agent_data).must_equal 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11'
82
+ end
83
+
84
+ it 'allows easy setting of custom data' do
85
+ now = Time.now
86
+ contact = Intercom::Contact.new
87
+ contact.custom_attributes['mad'] = 123
88
+ contact.custom_attributes['other'] = now.to_i
89
+ contact.custom_attributes['thing'] = 'yay'
90
+ _(contact.to_hash['custom_attributes']).must_equal 'mad' => 123, 'other' => now.to_i, 'thing' => 'yay'
91
+ end
92
+
93
+ it 'rejects nested data structures in custom_attributes' do
94
+ contact = Intercom::Contact.new
95
+
96
+ _(proc { contact.custom_attributes['thing'] = [1] }).must_raise(ArgumentError)
97
+ _(proc { contact.custom_attributes['thing'] = { 1 => 2 } }).must_raise(ArgumentError)
98
+ _(proc { contact.custom_attributes['thing'] = { 1 => { 2 => 3 } } }).must_raise(ArgumentError)
99
+
100
+ contact = Intercom::Contact.new(test_contact)
101
+ _(proc { contact.custom_attributes['thing'] = [1] }).must_raise(ArgumentError)
102
+ end
103
+
104
+ describe 'incrementing custom_attributes fields' do
105
+ before :each do
106
+ @now = Time.now
107
+ @contact = Intercom::Contact.new('email' => 'jo@example.com', :external_id => 'i-1224242', :custom_attributes => { 'mad' => 123, 'another' => 432, 'other' => @now.to_i, :thing => 'yay' })
108
+ end
109
+
110
+ it 'increments up by 1 with no args' do
111
+ @contact.increment('mad')
112
+ _(@contact.to_hash['custom_attributes']['mad']).must_equal 124
113
+ end
114
+
115
+ it 'increments up by given value' do
116
+ @contact.increment('mad', 4)
117
+ _(@contact.to_hash['custom_attributes']['mad']).must_equal 127
118
+ end
119
+
120
+ it 'increments down by given value' do
121
+ @contact.increment('mad', -1)
122
+ _(@contact.to_hash['custom_attributes']['mad']).must_equal 122
123
+ end
124
+
125
+ it 'can increment new custom data fields' do
126
+ @contact.increment('new_field', 3)
127
+ _(@contact.to_hash['custom_attributes']['new_field']).must_equal 3
128
+ end
129
+
130
+ it 'can call increment on the same key twice and increment by 2' do
131
+ @contact.increment('mad')
132
+ @contact.increment('mad')
133
+ _(@contact.to_hash['custom_attributes']['mad']).must_equal 125
134
+ end
135
+ end
136
+
137
+ describe 'decrementing custom_attributes fields' do
138
+ before :each do
139
+ @now = Time.now
140
+ @contact = Intercom::Contact.new('email' => 'jo@example.com', :external_id => 'i-1224242', :custom_attributes => { 'mad' => 123, 'another' => 432, 'other' => @now.to_i, :thing => 'yay' })
141
+ end
142
+
143
+ it 'decrements down by 1 with no args' do
144
+ @contact.decrement('mad')
145
+ _(@contact.to_hash['custom_attributes']['mad']).must_equal 122
146
+ end
147
+
148
+ it 'decrements down by given value' do
149
+ @contact.decrement('mad', 3)
150
+ _(@contact.to_hash['custom_attributes']['mad']).must_equal 120
151
+ end
152
+
153
+ it 'can decrement new custom data fields' do
154
+ @contact.decrement('new_field', 5)
155
+ _(@contact.to_hash['custom_attributes']['new_field']).must_equal(-5)
156
+ end
157
+
158
+ it 'can call decrement on the same key twice and decrement by 2' do
159
+ @contact.decrement('mad')
160
+ @contact.decrement('mad')
161
+ _(@contact.to_hash['custom_attributes']['mad']).must_equal 121
162
+ end
163
+ end
164
+
165
+ it 'saves a contact (always sends custom_attributes)' do
166
+ contact = Intercom::Contact.new('email' => 'jo@example.com', :external_id => 'i-1224242')
167
+ client.expects(:post).with('/contacts', 'email' => 'jo@example.com', 'external_id' => 'i-1224242', 'custom_attributes' => {}).returns('email' => 'jo@example.com', 'external_id' => 'i-1224242')
21
168
  client.contacts.save(contact)
22
169
  end
23
170
 
24
- describe 'converting' do
25
- let(:contact) { Intercom::Contact.from_api(user_id: 'contact_id') }
26
- let(:user) { Intercom::User.from_api(id: 'user_id') }
171
+ it 'can save a contact with a nil email' do
172
+ contact = Intercom::Contact.new('email' => nil, :external_id => 'i-1224242')
173
+ client.expects(:post).with('/contacts', 'custom_attributes' => {}, 'email' => nil, 'external_id' => 'i-1224242').returns('email' => nil, 'external_id' => 'i-1224242')
174
+ client.contacts.save(contact)
175
+ end
176
+
177
+ it 'can use client.contacts.create for convenience' do
178
+ client.expects(:post).with('/contacts', 'custom_attributes' => {}, 'email' => 'jo@example.com', 'external_id' => 'i-1224242').returns('email' => 'jo@example.com', 'external_id' => 'i-1224242')
179
+ contact = client.contacts.create('email' => 'jo@example.com', :external_id => 'i-1224242')
180
+ _(contact.email).must_equal 'jo@example.com'
181
+ end
27
182
 
28
- it do
29
- client.expects(:post).with(
30
- "/contacts/convert",
31
- {
32
- contact: { user_id: contact.user_id },
33
- user: { 'id' => user.id }
34
- }
35
- ).returns(test_user)
183
+ it 'updates the contact with attributes as set by the server' do
184
+ client.expects(:post).with('/contacts', 'email' => 'jo@example.com', 'external_id' => 'i-1224242', 'custom_attributes' => {}).returns('email' => 'jo@example.com', 'external_id' => 'i-1224242', 'session_count' => 4)
185
+ contact = client.contacts.create('email' => 'jo@example.com', :external_id => 'i-1224242')
186
+ _(contact.session_count).must_equal 4
187
+ end
188
+
189
+ it 'allows setting dates to nil without converting them to 0' do
190
+ client.expects(:post).with('/contacts', 'email' => 'jo@example.com', 'custom_attributes' => {}, 'remote_created_at' => nil).returns('email' => 'jo@example.com')
191
+ contact = client.contacts.create('email' => 'jo@example.com', 'remote_created_at' => nil)
192
+ assert_nil contact.remote_created_at
193
+ end
36
194
 
37
- client.contacts.convert(contact, user)
195
+ it 'sets/gets rw keys' do
196
+ params = { 'email' => 'me@example.com', :external_id => 'abc123', 'name' => 'Bob Smith', 'last_seen_ip' => '1.2.3.4', 'last_seen_contact_agent' => 'ie6', 'created_at' => Time.now }
197
+ contact = Intercom::Contact.new(params)
198
+ custom_attributes = (params.keys + ['custom_attributes']).map(&:to_s).sort
199
+ _(contact.to_hash.keys.sort).must_equal custom_attributes
200
+ params.keys.each do |key|
201
+ _(contact.send(key).to_s).must_equal params[key].to_s
38
202
  end
39
203
  end
40
204
 
41
- it "returns a ClientCollectionProxy for all without making any requests" do
205
+ it 'will allow extra attributes in response from api' do
206
+ contact = Intercom::Contact.send(:from_api, 'new_param' => 'some value')
207
+ _(contact.new_param).must_equal 'some value'
208
+ end
209
+
210
+ it 'returns a BaseCollectionProxy for all without making any requests' do
42
211
  client.expects(:execute_request).never
43
212
  all = client.contacts.all
44
- all.must_be_instance_of(Intercom::ClientCollectionProxy)
213
+ _(all).must_be_instance_of(Intercom::BaseCollectionProxy)
214
+ end
215
+
216
+ it 'can print contacts without crashing' do
217
+ client.expects(:get).with('/contacts', 'email' => 'bo@example.com').returns(test_contact)
218
+ contact = client.contacts.find('email' => 'bo@example.com')
219
+
220
+ begin
221
+ orignal_stdout = $stdout
222
+ $stdout = StringIO.new
223
+
224
+ puts contact
225
+ p contact
226
+ ensure
227
+ $stdout = orignal_stdout
228
+ end
229
+ end
230
+
231
+ it 'fetches a contact' do
232
+ client.expects(:get).with('/contacts', 'email' => 'bo@example.com').returns(test_contact)
233
+ contact = client.contacts.find('email' => 'bo@example.com')
234
+ _(contact.email).must_equal 'bob@example.com'
235
+ _(contact.name).must_equal 'Joe Schmoe'
236
+ _(contact.session_count).must_equal 123
237
+ end
238
+
239
+ it 'can update a contact with an id' do
240
+ contact = Intercom::Contact.new(id: 'de45ae78gae1289cb')
241
+ client.expects(:put).with('/contacts/de45ae78gae1289cb', 'custom_attributes' => {})
242
+ client.contacts.save(contact)
45
243
  end
46
244
 
47
- it "deletes a contact" do
48
- contact = Intercom::Contact.new("id" => "1")
49
- client.expects(:delete).with("/contacts/1", {}).returns(contact)
245
+ it 'deletes a contact' do
246
+ contact = Intercom::Contact.new('id' => '1')
247
+ client.expects(:delete).with('/contacts/1', {}).returns(contact)
50
248
  client.contacts.delete(contact)
51
249
  end
52
250
 
53
- it "sends a request for a hard deletion" do
54
- contact = Intercom::Contact.new("id" => "1")
55
- client.expects(:post).with("/user_delete_requests", {intercom_user_id: "1"}).returns({id: contact.id})
56
- client.contacts.request_hard_delete(contact)
251
+ it 'archives a contact' do
252
+ contact = Intercom::Contact.new('id' => '1')
253
+ client.expects(:post).with('/contacts/1/archive', {})
254
+ client.contacts.archive(contact)
57
255
  end
58
256
 
257
+ it 'unarchives a contact' do
258
+ contact = Intercom::Contact.new('id' => '1')
259
+ client.expects(:post).with('/contacts/1/unarchive', {})
260
+ client.contacts.unarchive(contact)
261
+ end
262
+
263
+ describe 'merging' do
264
+ let(:lead) { Intercom::Contact.from_api(external_id: 'contact_id', role: 'lead') }
265
+ let(:user) { Intercom::Contact.from_api(id: 'external_id', role: 'user') }
266
+
267
+ it 'should be successful with a lead and user' do
268
+ client.expects(:post).with('/contacts/merge',
269
+ from: lead.id, into: user.id).returns(test_contact)
270
+
271
+ client.contacts.merge(lead, user)
272
+ end
273
+ end
274
+
275
+ describe 'nested resources' do
276
+ let(:contact) { Intercom::Contact.new(id: '1', client: client) }
277
+ let(:contact_no_tags) { Intercom::Contact.new(id: '2', client: client, tags: []) }
278
+ let(:company) { Intercom::Company.new(id: '1') }
279
+ let(:tag) { Intercom::Tag.new(id: '1') }
280
+ let(:note) { Intercom::Note.new(body: "<p>Text for the note</p>") }
281
+
282
+ it 'returns a collection proxy for listing notes' do
283
+ proxy = contact.notes
284
+ _(proxy.resource_name).must_equal 'notes'
285
+ _(proxy.url).must_equal '/contacts/1/notes'
286
+ _(proxy.resource_class).must_equal Intercom::Note
287
+ end
288
+
289
+ it 'returns a collection proxy for listing segments' do
290
+ proxy = contact.segments
291
+ _(proxy.resource_name).must_equal 'segments'
292
+ _(proxy.url).must_equal '/contacts/1/segments'
293
+ _(proxy.resource_class).must_equal Intercom::Segment
294
+ end
295
+
296
+ it 'returns a collection proxy for listing tags' do
297
+ proxy = contact.tags
298
+ _(proxy.resource_name).must_equal 'tags'
299
+ _(proxy.url).must_equal '/contacts/1/tags'
300
+ _(proxy.resource_class).must_equal Intercom::Tag
301
+ end
302
+
303
+ it 'returns correct tags from differring contacts' do
304
+ client.expects(:get).with('/contacts/1/tags', {}).returns({
305
+ 'type' => 'tag.list',
306
+ 'tags' => [
307
+ {
308
+ 'type' => 'tag',
309
+ 'id' => '1',
310
+ 'name' => 'VIP Customer'
311
+ },
312
+ {
313
+ 'type' => 'tag',
314
+ 'id' => '2',
315
+ 'name' => 'Test tag'
316
+ }
317
+ ]
318
+ })
319
+
320
+ _(contact_no_tags.tags.map{ |t| t.id }).must_equal []
321
+ _(contact.tags.map{ |t| t.id }).must_equal ['1', '2']
322
+ end
323
+
324
+ it 'returns a collection proxy for listing companies' do
325
+ proxy = contact.companies
326
+ _(proxy.resource_name).must_equal 'companies'
327
+ _(proxy.url).must_equal '/contacts/1/companies'
328
+ _(proxy.resource_class).must_equal Intercom::Company
329
+ end
330
+
331
+ it 'adds a note to a contact' do
332
+ client.expects(:post).with('/contacts/1/notes', {body: note.body}).returns(note.to_hash)
333
+ contact.create_note({body: note.body})
334
+ end
335
+
336
+ it 'adds a tag to a contact' do
337
+ client.expects(:post).with('/contacts/1/tags', "id": tag.id).returns(tag.to_hash)
338
+ contact.add_tag({ "id": tag.id })
339
+ end
340
+
341
+ it 'removes a tag from a contact' do
342
+ client.expects(:delete).with("/contacts/1/tags/#{tag.id}", "id": tag.id ).returns(tag.to_hash)
343
+ contact.remove_tag({ "id": tag.id })
344
+ end
345
+
346
+ it 'adds a contact to a company' do
347
+ client.expects(:post).with('/contacts/1/companies', "id": company.id).returns(test_company)
348
+ contact.add_company({ "id": tag.id })
349
+ end
350
+
351
+ it 'removes a contact from a company' do
352
+ client.expects(:delete).with("/contacts/1/companies/#{company.id}", "id": tag.id ).returns(test_company)
353
+ contact.remove_company({ "id": tag.id })
354
+ end
355
+
356
+ describe 'just after creating the contact' do
357
+ let(:contact) do
358
+ contact = Intercom::Contact.new('email' => 'jo@example.com', :external_id => 'i-1224242')
359
+ client.expects(:post).with('/contacts', 'email' => 'jo@example.com', 'external_id' => 'i-1224242', 'custom_attributes' => {})
360
+ .returns('id' => 1, 'email' => 'jo@example.com', 'external_id' => 'i-1224242')
361
+ client.contacts.save(contact)
362
+ end
363
+
364
+ it 'returns a collection proxy for listing notes' do
365
+ proxy = contact.notes
366
+ _(proxy.resource_name).must_equal 'notes'
367
+ _(proxy.url).must_equal '/contacts/1/notes'
368
+ _(proxy.resource_class).must_equal Intercom::Note
369
+ end
370
+
371
+ it 'returns a collection proxy for listing tags' do
372
+ proxy = contact.tags
373
+ _(proxy.resource_name).must_equal 'tags'
374
+ _(proxy.url).must_equal '/contacts/1/tags'
375
+ _(proxy.resource_class).must_equal Intercom::Tag
376
+ end
377
+
378
+ it 'returns a collection proxy for listing companies' do
379
+ proxy = contact.companies
380
+ _(proxy.resource_name).must_equal 'companies'
381
+ _(proxy.url).must_equal '/contacts/1/companies'
382
+ _(proxy.resource_class).must_equal Intercom::Company
383
+ end
384
+
385
+ it 'adds a note to a contact' do
386
+ client.expects(:post).with('/contacts/1/notes', {body: note.body}).returns(note.to_hash)
387
+ contact.create_note({body: note.body})
388
+ end
389
+
390
+ it 'adds a tag to a contact' do
391
+ client.expects(:post).with('/contacts/1/tags', "id": tag.id).returns(tag.to_hash)
392
+ contact.add_tag({ "id": tag.id })
393
+ end
394
+
395
+ it 'removes a tag from a contact' do
396
+ client.expects(:delete).with("/contacts/1/tags/#{tag.id}", "id": tag.id ).returns(tag.to_hash)
397
+ contact.remove_tag({ "id": tag.id })
398
+ end
399
+
400
+ it 'adds a contact to a company' do
401
+ client.expects(:post).with('/contacts/1/companies', "id": company.id).returns(test_company)
402
+ contact.add_company({ "id": tag.id })
403
+ end
404
+
405
+ it 'removes a contact from a company' do
406
+ client.expects(:delete).with("/contacts/1/companies/#{company.id}", "id": tag.id ).returns(test_company)
407
+ contact.remove_company({ "id": tag.id })
408
+ end
409
+ end
410
+ end
59
411
  end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe "Intercom::Conversation" do
4
- let (:client) { Intercom::Client.new(app_id: 'app_id', api_key: 'api_key') }
4
+ let(:client) { Intercom::Client.new(token: 'token') }
5
5
 
6
6
  it "gets a conversation" do
7
7
  client.expects(:get).with("/conversations/147", {}).returns(test_conversation)
@@ -53,11 +53,59 @@ describe "Intercom::Conversation" do
53
53
  client.conversations.snooze(id: '147', admin_id: '123', snoozed_until: tomorrow)
54
54
  end
55
55
 
56
- # it "creates a subscription" do
57
- # client.expects(:post).with("/subscriptions", {'url' => "http://example.com", 'topics' => ["user.created"]}).returns(test_subscription)
58
- # subscription = client.subscriptions.create(:url => "http://example.com", :topics => ["user.created"])
59
- # subscription.request.topics[0].must_equal "user.created"
60
- # subscription.request.url.must_equal "http://example.com"
61
- # end
56
+ it 'runs assignment rules on a conversation' do
57
+ client.expects(:post).with('/conversations/147/run_assignment_rules', {}).returns(test_conversation)
58
+ client.conversations.run_assignment_rules('147')
59
+ end
60
+
61
+ describe 'nested resources' do
62
+ let(:conversation) { Intercom::Conversation.new('id' => '1', 'client' => client) }
63
+ let(:tag) { Intercom::Tag.new('id' => '1') }
64
+
65
+ it 'adds a tag to a conversation' do
66
+ client.expects(:post).with("/conversations/1/tags", { 'id': tag.id, 'admin_id': test_admin['id'] }).returns(tag.to_hash)
67
+ conversation.add_tag({ "id": tag.id, "admin_id": test_admin['id'] })
68
+ end
69
+
70
+ it 'does not add a tag to a conversation if no admin_id is passed' do
71
+ client.expects(:post).with("/conversations/1/tags", { 'id': tag.id }).returns(nil)
72
+ _(proc { conversation.add_tag({ "id": tag.id }) }).must_raise Intercom::HttpError
73
+ end
74
+
75
+ it 'removes a tag from a conversation' do
76
+ client.expects(:delete).with("/conversations/1/tags/1", { "id": tag.id, "admin_id": test_admin['id'] }).returns(tag.to_hash)
77
+ conversation.remove_tag({ "id": tag.id, "admin_id": test_admin['id'] })
78
+ end
62
79
 
80
+ it 'does not remove a tag from a conversation if no admin_id is passed' do
81
+ client.expects(:delete).with("/conversations/1/tags/1", { "id": tag.id }).returns(nil)
82
+ _(proc { conversation.remove_tag({ "id": tag.id }) }).must_raise Intercom::HttpError
83
+ end
84
+
85
+ describe 'contacts' do
86
+ let(:response) do
87
+ {
88
+ customers: [
89
+ { type: test_contact['type'], id: test_contact['id'] }
90
+ ]
91
+ }
92
+ end
93
+
94
+ it 'adds a contact to a conversation' do
95
+ client.expects(:post)
96
+ .with("/conversations/1/customers",
97
+ { admin_id: test_admin['id'], customer: { intercom_user_id: test_contact['id'] } })
98
+ .returns(response.to_hash)
99
+ conversation.add_contact(admin_id: test_admin['id'], customer: { intercom_user_id: test_contact['id'] })
100
+ end
101
+
102
+ it 'removes a contact from a conversation' do
103
+ client.expects(:delete)
104
+ .with("/conversations/1/customers/aaaaaaaaaaaaaaaaaaaaaaaa",
105
+ { id: 'aaaaaaaaaaaaaaaaaaaaaaaa', admin_id: '1234' })
106
+ .returns(response.to_hash)
107
+ conversation.remove_contact(id: test_contact['id'], admin_id: test_admin['id'])
108
+ end
109
+ end
110
+ end
63
111
  end
@@ -1,24 +1,24 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe "Intercom::Count" do
4
- let (:client) { Intercom::Client.new(app_id: 'app_id', api_key: 'api_key') }
4
+ let(:client) { Intercom::Client.new(token: 'token') }
5
5
 
6
6
  it 'should get app wide counts' do
7
7
  client.expects(:get).with("/counts", {}).returns(test_app_count)
8
8
  counts = client.counts.for_app
9
- counts.tag['count'].must_equal(341)
9
+ _(counts.tag['count']).must_equal(341)
10
10
  end
11
11
 
12
12
  it 'should get type counts' do
13
13
  client.expects(:get).with("/counts", {type: 'user', count: 'segment'}).returns(test_segment_count)
14
14
  counts = client.counts.for_type(type: 'user', count: 'segment')
15
- counts.user['segment'][4]["segment 1"].must_equal(1)
15
+ _(counts.user['segment'][4]["segment 1"]).must_equal(1)
16
16
  end
17
17
 
18
18
  it 'should not include count param when nil' do
19
19
  client.expects(:get).with("/counts", {type: 'conversation'}).returns(test_conversation_count)
20
20
  counts = client.counts.for_type(type: 'conversation')
21
- counts.conversation.must_equal({
21
+ _(counts.conversation).must_equal({
22
22
  "assigned" => 1,
23
23
  "closed" => 15,
24
24
  "open" => 1,
@@ -0,0 +1,40 @@
1
+ require "spec_helper"
2
+
3
+ describe "Intercom::DataAttribute" do
4
+ let(:client) { Intercom::Client.new(token: 'token') }
5
+
6
+ it "returns a CollectionProxy for all without making any requests" do
7
+ client.expects(:execute_request).never
8
+ all = client.data_attributes.all
9
+ _(all).must_be_instance_of(Intercom::ClientCollectionProxy)
10
+ end
11
+
12
+
13
+ it "creates a new data attribute" do
14
+ client.expects(:post).with("/data_attributes", { "name" => "blah", "model" => "contact", "data_type" => "string" }).returns(status: 200)
15
+ client.data_attributes.create("name": "blah",
16
+ "model": "contact",
17
+ "data_type": "string" )
18
+ end
19
+
20
+ it "updates an existing attribute" do
21
+ attribute = Intercom::DataAttribute.new("id": 123,
22
+ "name": "blah",
23
+ "model": "contact",
24
+ "data_type": "string")
25
+ client.expects(:put).with("/data_attributes/#{attribute.id}", { "name" => "New name", "model" => "contact", "data_type" => "string" })
26
+ attribute.name = "New name"
27
+ client.data_attributes.save(attribute)
28
+ _(attribute.name).must_equal "New name"
29
+ end
30
+
31
+ it 'gets a list of attributes' do
32
+ client.expects(:get).with("/data_attributes", {}).returns(test_data_attribute_list)
33
+ client.data_attributes.all.each { |d| }
34
+ end
35
+
36
+ it 'finds all customer or company attributes' do
37
+ client.expects(:get).with("/data_attributes", { "model": "contact" }).returns(test_data_attribute_list)
38
+ client.data_attributes.find_all({"model": "contact"}).each { |d| }
39
+ end
40
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Intercom::ClientCollectionProxy do
6
+ let(:client) { Intercom::Client.new(token: 'token') }
7
+ let(:lead_json) do
8
+ { 'type' => 'contact.list', 'contacts' => [{ 'type' => 'contact', 'id' => 'id' }] }
9
+ end
10
+
11
+ it 'stops iterating if no next link' do
12
+ client.expects(:get).with('/contacts', {}).returns(lead_json)
13
+ client.deprecated__leads.all.each do |company|
14
+ _(company.class).must_equal Intercom::Lead
15
+ end
16
+ end
17
+ end