intercom 3.9.5 → 4.1.3

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.
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