Skip to content

Commit 1fbb5e4

Browse files
committed
Merge pull request intercom#113 from jkeyes/leads
Adding support for Leads (previously known as Contacts).
2 parents 26abaf0 + e9a30ea commit 1fbb5e4

File tree

10 files changed

+132
-3
lines changed

10 files changed

+132
-3
lines changed

intercom/api_operations/convert.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# -*- coding: utf-8 -*-
2+
3+
4+
class Convert(object):
5+
6+
def convert(self, contact, user):
7+
self.client.post(
8+
'/contacts/convert',
9+
{
10+
'contact': {'user_id': contact.user_id},
11+
'user': self.identity_hash(user)
12+
}
13+
)

intercom/api_operations/delete.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ class Delete(object):
88
def delete(self, obj):
99
collection = utils.resource_class_to_collection_name(
1010
self.collection_class)
11-
self.client.delete("/%s/%s/" % (collection, obj.id), {})
11+
self.client.delete("/%s/%s" % (collection, obj.id), {})
1212
return obj

intercom/client.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ def users(self):
6868
from intercom.service import user
6969
return user.User(self)
7070

71+
@property
72+
def leads(self):
73+
from intercom.service import lead
74+
return lead.Lead(self)
75+
7176
@property
7277
def jobs(self):
7378
from intercom.service import job

intercom/collection_proxy.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import six
44
from intercom import HttpError
5+
from intercom import utils
56

67

78
class CollectionProxy(six.Iterator):
@@ -12,6 +13,12 @@ def __init__(
1213

1314
self.client = client
1415

16+
# resource name
17+
self.resource_name = utils.resource_class_to_collection_name(collection_cls)
18+
19+
# resource class
20+
self.resource_class = collection_cls
21+
1522
# needed to create class instances of the resource
1623
self.collection_cls = collection_cls
1724

intercom/lead.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from intercom.traits.api_resource import Resource
4+
5+
6+
class Lead(Resource):
7+
8+
update_verb = 'put'
9+
identity_vars = ['email', 'user_id']
10+
collection_name = 'contacts'
11+
12+
@property
13+
def flat_store_attributes(self):
14+
return ['custom_attributes']

intercom/service/lead.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# -*- coding: utf-8 -*- # noqa
2+
3+
from intercom import lead
4+
from intercom.api_operations.all import All
5+
from intercom.api_operations.convert import Convert
6+
from intercom.api_operations.find import Find
7+
from intercom.api_operations.find_all import FindAll
8+
from intercom.api_operations.delete import Delete
9+
from intercom.api_operations.save import Save
10+
from intercom.api_operations.load import Load
11+
from intercom.service.base_service import BaseService
12+
13+
14+
class Lead(BaseService, All, Find, FindAll, Delete, Save, Load, Convert):
15+
"""Leads are useful for representing logged-out users of your application.
16+
17+
Ref: https://developers.intercom.io/reference#leads
18+
"""
19+
20+
@property
21+
def collection_class(self):
22+
"""The collection class that represents this resource."""
23+
return lead.Lead

intercom/user.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
class User(Resource, IncrementableAttributes):
88

99
update_verb = 'post'
10-
identity_vars = ['email', 'user_id']
10+
identity_vars = ['id', 'email', 'user_id']
1111

1212
@property
1313
def flat_store_attributes(self):

intercom/utils.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ def constantize_singular_resource_name(resource_name):
2525

2626

2727
def resource_class_to_collection_name(cls):
28+
if hasattr(cls, 'collection_name'):
29+
return cls.collection_name
2830
return pluralize(cls.__name__.lower())
2931

3032

tests/unit/test_lead.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# -*- coding: utf-8 -*- # noqa
2+
3+
import mock
4+
import unittest
5+
6+
from intercom.collection_proxy import CollectionProxy
7+
from intercom.client import Client
8+
from intercom.lead import Lead
9+
from intercom.user import User
10+
from mock import patch
11+
from nose.tools import istest
12+
from tests.unit import get_user
13+
14+
15+
class LeadTest(unittest.TestCase): # noqa
16+
17+
def setUp(self): # noqa
18+
self.client = Client()
19+
20+
@istest
21+
def it_should_be_listable(self): # noqa
22+
proxy = self.client.leads.all()
23+
self.assertEquals('contacts', proxy.resource_name)
24+
self.assertEquals('/contacts', proxy.finder_url)
25+
self.assertEquals(Lead, proxy.resource_class)
26+
27+
@istest
28+
def it_should_not_throw_errors_when_there_are_no_parameters(self): # noqa
29+
with patch.object(Client, 'post') as mock_method: # noqa
30+
self.client.leads.create()
31+
32+
@istest
33+
def it_can_update_a_lead_with_an_id(self): # noqa
34+
lead = Lead(id="de45ae78gae1289cb")
35+
with patch.object(Client, 'put') as mock_method: # noqa
36+
self.client.leads.save(lead)
37+
mock_method.assert_called_once_with(
38+
'/contacts/de45ae78gae1289cb', {'custom_attributes': {}})
39+
40+
@istest
41+
def it_can_convert(self): # noqa
42+
lead = Lead.from_api({'user_id': 'contact_id'})
43+
user = User.from_api({'id': 'user_id'})
44+
45+
with patch.object(Client, 'post', returns=get_user()) as mock_method: # noqa
46+
self.client.leads.convert(lead, user)
47+
mock_method.assert_called_once_with(
48+
'/contacts/convert',
49+
{
50+
'contact': {'user_id': lead.user_id},
51+
'user': {'id': user.id}
52+
})
53+
54+
@istest
55+
def it_returns_a_collectionproxy_for_all_without_making_any_requests(self): # noqa
56+
with mock.patch('intercom.request.Request.send_request_to_path', new_callable=mock.NonCallableMock): # noqa
57+
res = self.client.leads.all()
58+
self.assertIsInstance(res, CollectionProxy)
59+
60+
@istest
61+
def it_deletes_a_contact(self): # noqa
62+
lead = Lead(id="1")
63+
with patch.object(Client, 'delete') as mock_method: # noqa
64+
self.client.leads.delete(lead)
65+
mock_method.assert_called_once_with('/contacts/1', {})

tests/unit/test_user.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ def it_deletes_a_user(self):
273273
with patch.object(Client, 'delete', return_value={}) as mock_method:
274274
user = self.client.users.delete(user)
275275
eq_(user.id, "1")
276-
mock_method.assert_called_once_with('/users/1/', {})
276+
mock_method.assert_called_once_with('/users/1', {})
277277

278278
@istest
279279
def it_can_use_user_create_for_convenience(self):

0 commit comments

Comments
 (0)