Add unit test for {c:44cc749}
[hermes] / package / test / unit / test_facebook.py
1 from org.maemo.hermes.engine.facebook.service import Service
2 from org.maemo.hermes.engine.facebook.api import FacebookApi
3 from org.maemo.hermes.engine.names import canonical
4 from org.maemo.hermes.engine.friend import Friend
5 import unittest
6
7
8 class FakeContact():
9     id_counter = 0
10     def __init__(self, name, addr, id=None):
11         self.name = name;
12         self.urls = addr
13         self.id = id or FakeContact.id_counter
14         FakeContact.id_counter = FakeContact.id_counter + 1;
15     def get_urls(self):
16         return self.urls
17     def get_name(self):
18         return self.name
19     def get_identifiers(self):
20         return [canonical(self.name)]
21     
22 class FakeFacebookApi():
23     friends = []
24     
25     def get_friends(self):
26         return FakeFacebookApi.friends
27     
28 class FakeOAuth():
29     def authorise(self, authorise_url, access_token_url, args = None):
30         pass
31     
32     def request(self, url, args = None):
33         if url == 'https://graph.facebook.com/me':
34             return '{"id":"1234567","name":"Maemo Hermes"}'
35         
36         elif url == 'https://graph.facebook.com/me/friends':
37             return '{"data":[{"id":"1","name":"J Smith","website":"http:\/\/www.example.org"},{"id":"2","name":"P Barnum","picture":"http://fbcn.example.com/32939012.jpg"}]}'
38         
39         else:
40             raise Exception("Unknown URL: %s" % (url))
41         
42     def get_access_token(self):
43         return 'XXX'
44         
45
46 class TestFacebookService(unittest.TestCase):
47     
48     def setUp(self):
49         self.testee = Service("facebook", FakeFacebookApi())
50         
51     
52     def test_that_get_friends_to_create_contacts_for_works(self):
53         def run_test(expected_length):
54             self._fake_server_response([{'id':'123456','name':'Facebook Junkie', 'birthday':'now'}])
55             self._run_service([])
56             friends = self.testee.get_friends_to_create_contacts_for()
57             assert len(friends) == expected_length
58             
59         # default is to NOT create contacts
60         self.testee = Service("facebook", FakeFacebookApi())
61         run_test(0)
62         
63         # passing False explicitly
64         self.testee = Service("facebook", FakeFacebookApi(), False)
65         run_test(0)
66         
67         # passing True to constructor
68         self.testee = Service("facebook", FakeFacebookApi(), True)
69         run_test(1)
70         
71     
72     def test_that_gftccf_returns_friends_with_birth_date(self):
73         self.testee = Service("facebook", FakeFacebookApi(), True)
74         bday = '1980-10-15'
75         props_with_bday = {'id':'123456','name':'Facebook Junkie', 'birthday':bday}
76         props_without = {'id':'123457','name':'Johnny Secret'}
77         self._fake_server_response([props_with_bday, props_without])
78         self._run_service([])
79         
80         assert len(self.testee.get_friends()) == 2
81         friends = self.testee.get_friends_to_create_contacts_for()
82         assert len(friends) == 1
83         assert friends[0].has_birthday_date()
84         assert friends[0].get_birthday_date() == bday 
85         
86         
87     def test_that_process_contact_returns_friend_object_for_known_contact(self):
88         known_url = 'http://www.facebook.com/profile.php?id=123456'
89         known_contact = FakeContact('Facebook Junkie', [known_url])
90         self._fake_server_response([{'id':'123456','name':'Facebook Junkie'}])
91         
92         self.testee.process_friends()
93         result = self.testee.process_contact(known_contact)
94         assert isinstance(result, Friend)
95
96
97     def test_that_process_contact_returns_None_for_unknown_contact(self):
98         known_contact = FakeContact('Facebook Junkie', [])
99         self._fake_server_response([])
100         
101         self.testee.process_friends()
102         result = self.testee.process_contact(known_contact)
103         assert result is None
104
105
106     def test_main_flow_one_match_by_url_one_by_name(self):
107         # arrange
108         self.existing_address = 'http://www.facebook.com/profile.php?id=123456'
109         self.existing_contact = FakeContact("Facebook Person", [self.existing_address])
110         existing_fake = {'id':'123456','name':'Name Doesnt Match but URL Does'}
111         
112         self.other_address = 'http://twitter.com/not/correct/site'
113         self.other_contact = FakeContact("Twitter Person", [self.other_address])
114         other_fake = {'id':'123','name':self.other_contact.get_name()}
115         
116         self.none_contact = FakeContact("No URLson", [])
117         
118         fake_data = [existing_fake, other_fake]
119         self._fake_server_response(fake_data)
120
121         # act        
122         self._run_service([self.existing_contact, self.other_contact, self.none_contact])
123         
124         # assert
125         friends = self.testee.get_friends()
126         contacts = self.testee.get_contacts_with_match()
127         assert len(friends) == 2
128         assert len(contacts) == 2
129         assert self.other_contact in contacts
130         assert self.other_contact == contacts[self.other_contact].get_contact()
131         assert self.existing_contact in contacts
132         assert self.existing_contact == contacts[self.existing_contact].get_contact()
133         assert self.none_contact not in contacts
134         
135         
136     def test_name_collision_avoided_by_previous_matching(self):
137         name = "Same Name"
138         contact_do_match = FakeContact(name, ["http://www.facebook.com/profile.php?id=123"], 1);
139         contact_no_match = FakeContact(name, [None], 2)
140         
141         data = [{'id':'123','name':name}]
142         self._fake_server_response(data)
143         
144         self._run_service([contact_no_match, contact_do_match])
145         
146         assert len(self.testee.get_unmatched_friends()) == 0
147         matchers = self.testee.get_contacts_with_match().keys()
148         assert len(matchers) == 1
149         assert matchers[0].id == 1
150
151       
152     def test_name_collision_avoided_only_one_person_matched(self):
153         name = "Same Name"
154         contact_do_match = FakeContact(name, ["Contact 1"]);
155         contact_no_match = FakeContact(name, ["Contact 2"])
156         
157         data = [{'id':'123','name':name}]
158         self._fake_server_response(data)
159         
160         self._run_service([contact_no_match, contact_do_match])
161         
162         matchers = self.testee.get_contacts_with_match().keys()
163         assert len(matchers) == 1
164         assert len(self.testee.get_unmatched_friends()) == 0
165         
166         
167     def _run_service(self, contacts):
168         for contact in contacts:
169             self.testee.pre_process_contact(contact)
170         self.testee.process_friends()
171         for contact in contacts:
172             self.testee.process_contact(contact)
173         
174     def _fake_server_response(self, data):
175         FakeFacebookApi.friends = data
176
177
178 class TestFacebookAPI(unittest.TestCase):
179
180     def setUp(self):
181         self.oauth = FakeOAuth()
182         self.api = FacebookApi(self.oauth)
183
184     def test_authenticate(self):
185         pass
186     
187     
188     def test_get_user(self):
189         assert self.api.get_user() == 'Maemo Hermes'
190        
191         
192     def test_get_friends(self):
193         friends = self.api.get_friends()
194         assert len(friends) == 2
195         assert friends[0]['name'] == 'J Smith'
196         assert friends[1]['id'] == '2'
197         assert friends[1]['picture'] == 'https://graph.facebook.com/2/picture?type=large&access_token=XXX'
198
199     
200 if __name__ == '__main__':
201     unittest.main()