intercom 3.9.5 → 4.2.1

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 (101) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +483 -234
  3. data/Rakefile +1 -1
  4. data/changes.txt +37 -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 +68 -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 +74 -0
  17. data/lib/intercom/client.rb +48 -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 +23 -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 +6 -0
  27. data/lib/intercom/export_content.rb +7 -0
  28. data/lib/intercom/extended_api_operations/segments.rb +3 -1
  29. data/lib/intercom/extended_api_operations/tags.rb +3 -1
  30. data/lib/intercom/lead.rb +21 -0
  31. data/lib/intercom/lib/dynamic_accessors.rb +9 -10
  32. data/lib/intercom/lib/typed_json_deserializer.rb +45 -35
  33. data/lib/intercom/note.rb +4 -0
  34. data/lib/intercom/phone_call_redirect.rb +7 -0
  35. data/lib/intercom/request.rb +39 -33
  36. data/lib/intercom/scroll_collection_proxy.rb +38 -42
  37. data/lib/intercom/search_collection_proxy.rb +30 -65
  38. data/lib/intercom/section.rb +23 -0
  39. data/lib/intercom/segment.rb +4 -0
  40. data/lib/intercom/service/article.rb +20 -0
  41. data/lib/intercom/service/base_service.rb +7 -0
  42. data/lib/intercom/service/collection.rb +24 -0
  43. data/lib/intercom/service/company.rb +2 -12
  44. data/lib/intercom/service/contact.rb +35 -10
  45. data/lib/intercom/service/conversation.rb +16 -3
  46. data/lib/intercom/service/data_attribute.rb +20 -0
  47. data/lib/intercom/service/export_content.rb +30 -0
  48. data/lib/intercom/service/lead.rb +41 -0
  49. data/lib/intercom/service/note.rb +4 -8
  50. data/lib/intercom/service/phone_call_redirect.rb +15 -0
  51. data/lib/intercom/service/section.rb +7 -0
  52. data/lib/intercom/service/subscription.rb +2 -2
  53. data/lib/intercom/service/subscription_type.rb +18 -0
  54. data/lib/intercom/service/tag.rb +9 -9
  55. data/lib/intercom/service/visitor.rb +17 -8
  56. data/lib/intercom/subscription_type.rb +12 -0
  57. data/lib/intercom/tag.rb +4 -0
  58. data/lib/intercom/traits/api_resource.rb +44 -18
  59. data/lib/intercom/traits/dirty_tracking.rb +8 -1
  60. data/lib/intercom/user.rb +12 -3
  61. data/lib/intercom/utils.rb +19 -3
  62. data/lib/intercom/version.rb +1 -1
  63. data/lib/intercom/visitor.rb +0 -2
  64. data/lib/intercom.rb +39 -22
  65. data/spec/spec_helper.rb +843 -520
  66. data/spec/unit/intercom/admin_spec.rb +2 -2
  67. data/spec/unit/intercom/article_spec.rb +40 -0
  68. data/spec/unit/intercom/base_collection_proxy_spec.rb +52 -0
  69. data/spec/unit/intercom/client_collection_proxy_spec.rb +41 -41
  70. data/spec/unit/intercom/client_spec.rb +25 -26
  71. data/spec/unit/intercom/collection_spec.rb +32 -0
  72. data/spec/unit/intercom/company_spec.rb +19 -15
  73. data/spec/unit/intercom/contact_spec.rb +402 -33
  74. data/spec/unit/intercom/conversation_spec.rb +60 -7
  75. data/spec/unit/intercom/count_spec.rb +4 -4
  76. data/spec/unit/intercom/data_attribute_spec.rb +40 -0
  77. data/spec/unit/intercom/deprecated_leads_collection_proxy_spec.rb +17 -0
  78. data/spec/unit/intercom/event_spec.rb +16 -11
  79. data/spec/unit/intercom/export_content_spec.rb +28 -0
  80. data/spec/unit/intercom/job_spec.rb +24 -24
  81. data/spec/unit/intercom/lead_spec.rb +57 -0
  82. data/spec/unit/intercom/lib/flat_store_spec.rb +22 -20
  83. data/spec/unit/intercom/message_spec.rb +1 -1
  84. data/spec/unit/intercom/note_spec.rb +4 -10
  85. data/spec/unit/intercom/phone_call_redirect.rb +12 -0
  86. data/spec/unit/intercom/request_spec.rb +14 -1
  87. data/spec/unit/intercom/scroll_collection_proxy_spec.rb +40 -39
  88. data/spec/unit/intercom/search_collection_proxy_spec.rb +32 -28
  89. data/spec/unit/intercom/section_spec.rb +32 -0
  90. data/spec/unit/intercom/segment_spec.rb +2 -2
  91. data/spec/unit/intercom/subscription_spec.rb +5 -6
  92. data/spec/unit/intercom/tag_spec.rb +28 -14
  93. data/spec/unit/intercom/team_spec.rb +2 -2
  94. data/spec/unit/intercom/traits/api_resource_spec.rb +107 -52
  95. data/spec/unit/intercom/user_spec.rb +224 -226
  96. data/spec/unit/intercom/visitor_spec.rb +49 -0
  97. data/spec/unit/intercom_spec.rb +5 -3
  98. metadata +44 -8
  99. data/lib/intercom/customer.rb +0 -10
  100. data/lib/intercom/service/customer.rb +0 -14
  101. data/spec/unit/intercom/visitors_spec.rb +0 -61
@@ -1,59 +1,428 @@
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
27
176
 
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)
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
36
182
 
37
- client.contacts.convert(contact, 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
194
+
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)
45
214
  end
46
215
 
47
- it "deletes a contact" do
48
- contact = Intercom::Contact.new("id" => "1")
49
- client.expects(:delete).with("/contacts/1", {}).returns(contact)
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)
243
+ end
244
+
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)
255
+ end
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
+ it 'deletes an archived contact' do
264
+ contact = Intercom::Contact.new('id' => '1','archived' =>true)
265
+ client.expects(:delete).with('/contacts/1', {})
266
+ client.contacts.delete_archived_contact("1")
57
267
  end
58
268
 
269
+ describe 'merging' do
270
+ let(:lead) { Intercom::Contact.from_api(external_id: 'contact_id', role: 'lead') }
271
+ let(:user) { Intercom::Contact.from_api(id: 'external_id', role: 'user') }
272
+
273
+ it 'should be successful with a lead and user' do
274
+ client.expects(:post).with('/contacts/merge',
275
+ from: lead.id, into: user.id).returns(test_contact)
276
+
277
+ client.contacts.merge(lead, user)
278
+ end
279
+ end
280
+
281
+ describe 'nested resources' do
282
+ let(:contact) { Intercom::Contact.new(id: '1', client: client) }
283
+ let(:contact_no_tags) { Intercom::Contact.new(id: '2', client: client, tags: []) }
284
+ let(:company) { Intercom::Company.new(id: '1') }
285
+ let(:subscription) { Intercom::Subscription.new(id: '1', client: client) }
286
+ let(:tag) { Intercom::Tag.new(id: '1') }
287
+ let(:note) { Intercom::Note.new(body: "<p>Text for the note</p>") }
288
+
289
+ it 'returns a collection proxy for listing notes' do
290
+ proxy = contact.notes
291
+ _(proxy.resource_name).must_equal 'notes'
292
+ _(proxy.url).must_equal '/contacts/1/notes'
293
+ _(proxy.resource_class).must_equal Intercom::Note
294
+ end
295
+
296
+ it 'returns a collection proxy for listing segments' do
297
+ proxy = contact.segments
298
+ _(proxy.resource_name).must_equal 'segments'
299
+ _(proxy.url).must_equal '/contacts/1/segments'
300
+ _(proxy.resource_class).must_equal Intercom::Segment
301
+ end
302
+
303
+ it 'returns a collection proxy for listing tags' do
304
+ proxy = contact.tags
305
+ _(proxy.resource_name).must_equal 'tags'
306
+ _(proxy.url).must_equal '/contacts/1/tags'
307
+ _(proxy.resource_class).must_equal Intercom::Tag
308
+ end
309
+
310
+ it 'returns correct tags from differring contacts' do
311
+ client.expects(:get).with('/contacts/1/tags', {}).returns({
312
+ 'type' => 'tag.list',
313
+ 'tags' => [
314
+ {
315
+ 'type' => 'tag',
316
+ 'id' => '1',
317
+ 'name' => 'VIP Customer'
318
+ },
319
+ {
320
+ 'type' => 'tag',
321
+ 'id' => '2',
322
+ 'name' => 'Test tag'
323
+ }
324
+ ]
325
+ })
326
+
327
+ _(contact_no_tags.tags.map{ |t| t.id }).must_equal []
328
+ _(contact.tags.map{ |t| t.id }).must_equal ['1', '2']
329
+ end
330
+
331
+ it 'returns a collection proxy for listing companies' do
332
+ proxy = contact.companies
333
+ _(proxy.resource_name).must_equal 'companies'
334
+ _(proxy.url).must_equal '/contacts/1/companies'
335
+ _(proxy.resource_class).must_equal Intercom::Company
336
+ end
337
+
338
+ it 'adds a note to a contact' do
339
+ client.expects(:post).with('/contacts/1/notes', {body: note.body}).returns(note.to_hash)
340
+ contact.create_note({body: note.body})
341
+ end
342
+
343
+ it 'adds a tag to a contact' do
344
+ client.expects(:post).with('/contacts/1/tags', "id": tag.id).returns(tag.to_hash)
345
+ contact.add_tag({ "id": tag.id })
346
+ end
347
+
348
+ it 'removes a subscription to a contact' do
349
+ client.expects(:delete).with("/contacts/1/subscriptions/#{subscription.id}", "id": subscription.id).returns(subscription.to_hash)
350
+ contact.remove_subscription_type({ "id": subscription.id })
351
+ end
352
+
353
+ it 'removes a tag from a contact' do
354
+ client.expects(:delete).with("/contacts/1/tags/#{tag.id}", "id": tag.id ).returns(tag.to_hash)
355
+ contact.remove_tag({ "id": tag.id })
356
+ end
357
+
358
+ it 'adds a contact to a company' do
359
+ client.expects(:post).with('/contacts/1/companies', "id": company.id).returns(test_company)
360
+ contact.add_company({ "id": tag.id })
361
+ end
362
+
363
+ it 'removes a contact from a company' do
364
+ client.expects(:delete).with("/contacts/1/companies/#{company.id}", "id": tag.id ).returns(test_company)
365
+ contact.remove_company({ "id": tag.id })
366
+ end
367
+
368
+ describe 'just after creating the contact' do
369
+ let(:contact) do
370
+ contact = Intercom::Contact.new('email' => 'jo@example.com', :external_id => 'i-1224242')
371
+ client.expects(:post).with('/contacts', 'email' => 'jo@example.com', 'external_id' => 'i-1224242', 'custom_attributes' => {})
372
+ .returns('id' => 1, 'email' => 'jo@example.com', 'external_id' => 'i-1224242')
373
+ client.contacts.save(contact)
374
+ end
375
+
376
+ it 'returns a collection proxy for listing notes' do
377
+ proxy = contact.notes
378
+ _(proxy.resource_name).must_equal 'notes'
379
+ _(proxy.url).must_equal '/contacts/1/notes'
380
+ _(proxy.resource_class).must_equal Intercom::Note
381
+ end
382
+
383
+ it 'returns a collection proxy for listing tags' do
384
+ proxy = contact.tags
385
+ _(proxy.resource_name).must_equal 'tags'
386
+ _(proxy.url).must_equal '/contacts/1/tags'
387
+ _(proxy.resource_class).must_equal Intercom::Tag
388
+ end
389
+
390
+ it 'returns a collection proxy for listing companies' do
391
+ proxy = contact.companies
392
+ _(proxy.resource_name).must_equal 'companies'
393
+ _(proxy.url).must_equal '/contacts/1/companies'
394
+ _(proxy.resource_class).must_equal Intercom::Company
395
+ end
396
+
397
+ it 'adds a note to a contact' do
398
+ client.expects(:post).with('/contacts/1/notes', {body: note.body}).returns(note.to_hash)
399
+ contact.create_note({body: note.body})
400
+ end
401
+
402
+ it 'adds a subscription to a contact' do
403
+ client.expects(:post).with('/contacts/1/subscriptions', "id": subscription.id).returns(subscription.to_hash)
404
+ contact.create_subscription_type({ "id": subscription.id })
405
+ end
406
+
407
+ it 'adds a tag to a contact' do
408
+ client.expects(:post).with('/contacts/1/tags', "id": tag.id).returns(tag.to_hash)
409
+ contact.add_tag({ "id": tag.id })
410
+ end
411
+
412
+ it 'removes a tag from a contact' do
413
+ client.expects(:delete).with("/contacts/1/tags/#{tag.id}", "id": tag.id ).returns(tag.to_hash)
414
+ contact.remove_tag({ "id": tag.id })
415
+ end
416
+
417
+ it 'adds a contact to a company' do
418
+ client.expects(:post).with('/contacts/1/companies', "id": company.id).returns(test_company)
419
+ contact.add_company({ "id": tag.id })
420
+ end
421
+
422
+ it 'removes a contact from a company' do
423
+ client.expects(:delete).with("/contacts/1/companies/#{company.id}", "id": tag.id ).returns(test_company)
424
+ contact.remove_company({ "id": tag.id })
425
+ end
426
+ end
427
+ end
59
428
  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)
@@ -13,6 +13,11 @@ describe "Intercom::Conversation" do
13
13
  client.conversations.all.each { |c| }
14
14
  end
15
15
 
16
+ it "can filter conversations based on params" do
17
+ client.expects(:get).with("/conversations", {type: 'user', intercom_user_id: '123456789'}).returns(test_conversation_list)
18
+ client.conversations.find_all(type: 'user', intercom_user_id: '123456789').each { |c| }
19
+ end
20
+
16
21
  it 'marks a conversation as read' do
17
22
  client.expects(:put).with('/conversations/147', { read: true })
18
23
  client.conversations.mark_read('147')
@@ -53,11 +58,59 @@ describe "Intercom::Conversation" do
53
58
  client.conversations.snooze(id: '147', admin_id: '123', snoozed_until: tomorrow)
54
59
  end
55
60
 
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
61
+ it 'runs assignment rules on a conversation' do
62
+ client.expects(:post).with('/conversations/147/run_assignment_rules', {}).returns(test_conversation)
63
+ client.conversations.run_assignment_rules('147')
64
+ end
65
+
66
+ describe 'nested resources' do
67
+ let(:conversation) { Intercom::Conversation.new('id' => '1', 'client' => client) }
68
+ let(:tag) { Intercom::Tag.new('id' => '1') }
69
+
70
+ it 'adds a tag to a conversation' do
71
+ client.expects(:post).with("/conversations/1/tags", { 'id': tag.id, 'admin_id': test_admin['id'] }).returns(tag.to_hash)
72
+ conversation.add_tag({ "id": tag.id, "admin_id": test_admin['id'] })
73
+ end
74
+
75
+ it 'does not add a tag to a conversation if no admin_id is passed' do
76
+ client.expects(:post).with("/conversations/1/tags", { 'id': tag.id }).returns(nil)
77
+ _(proc { conversation.add_tag({ "id": tag.id }) }).must_raise Intercom::HttpError
78
+ end
62
79
 
80
+ it 'removes a tag from a conversation' do
81
+ client.expects(:delete).with("/conversations/1/tags/1", { "id": tag.id, "admin_id": test_admin['id'] }).returns(tag.to_hash)
82
+ conversation.remove_tag({ "id": tag.id, "admin_id": test_admin['id'] })
83
+ end
84
+
85
+ it 'does not remove a tag from a conversation if no admin_id is passed' do
86
+ client.expects(:delete).with("/conversations/1/tags/1", { "id": tag.id }).returns(nil)
87
+ _(proc { conversation.remove_tag({ "id": tag.id }) }).must_raise Intercom::HttpError
88
+ end
89
+
90
+ describe 'contacts' do
91
+ let(:response) do
92
+ {
93
+ customers: [
94
+ { type: test_contact['type'], id: test_contact['id'] }
95
+ ]
96
+ }
97
+ end
98
+
99
+ it 'adds a contact to a conversation' do
100
+ client.expects(:post)
101
+ .with("/conversations/1/customers",
102
+ { admin_id: test_admin['id'], customer: { intercom_user_id: test_contact['id'] } })
103
+ .returns(response.to_hash)
104
+ conversation.add_contact(admin_id: test_admin['id'], customer: { intercom_user_id: test_contact['id'] })
105
+ end
106
+
107
+ it 'removes a contact from a conversation' do
108
+ client.expects(:delete)
109
+ .with("/conversations/1/customers/aaaaaaaaaaaaaaaaaaaaaaaa",
110
+ { id: 'aaaaaaaaaaaaaaaaaaaaaaaa', admin_id: '1234' })
111
+ .returns(response.to_hash)
112
+ conversation.remove_contact(id: test_contact['id'], admin_id: test_admin['id'])
113
+ end
114
+ end
115
+ end
63
116
  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