class TestAccountApiClient(TestCase): API_URL = "http://example.com/go" AUTH_TOKEN = "auth_token" def setUp(self): self.account_backend = FakeAccountApi("go/", self.AUTH_TOKEN) self.session = TestSession() self.adapter = FakeAccountApiAdapter(self.account_backend) self.simulate_api_up() def simulate_api_down(self): self.session.mount(self.API_URL, TestAdapter("API is down", 500)) def simulate_api_up(self): self.session.mount(self.API_URL, self.adapter) def make_client(self, auth_token=AUTH_TOKEN): return AccountApiClient(auth_token, api_url=self.API_URL, session=self.session) def assert_http_error(self, expected_status, func, *args, **kw): try: func(*args, **kw) except HTTPError as err: self.assertEqual(err.response.status_code, expected_status) else: self.fail("Expected HTTPError with status %s." % (expected_status, )) def assert_jsonrpc_exception(self, f, *args, **kw): try: f(*args, **kw) except Exception as err: self.assertTrue(isinstance(err, JsonRpcException)) self.assertTrue(isinstance(err.fault, unicode)) self.assertTrue(isinstance(err.fault_code, int)) self.assertTrue(isinstance(err.fault_string, unicode)) return err def test_assert_http_error(self): self.session.mount("http://bad.example.com/", TestAdapter("", 500)) def bad_req(): r = self.session.get("http://bad.example.com/") r.raise_for_status() # Fails when no exception is raised. self.assertRaises(self.failureException, self.assert_http_error, 404, lambda: None) # Fails when an HTTPError with the wrong status code is raised. self.assertRaises(self.failureException, self.assert_http_error, 404, bad_req) # Passes when an HTTPError with the expected status code is raised. self.assert_http_error(500, bad_req) # Non-HTTPError exceptions aren't caught. def raise_error(): raise ValueError() self.assertRaises(ValueError, self.assert_http_error, 404, raise_error) def test_default_session(self): client = AccountApiClient(self.AUTH_TOKEN) self.assertTrue(isinstance(client.session, Session)) def test_default_api_url(self): client = AccountApiClient(self.AUTH_TOKEN) self.assertEqual(client.api_url, "https://go.vumi.org/api/v1/go") def test_auth_failure(self): client = self.make_client(auth_token="bogus_token") self.assert_http_error(403, client.campaigns) def test_jsonrpc_error_handling(self): client = self.make_client() self.account_backend.add_error_response("campaigns", [], fault="Fault", fault_code=8002, fault_string="Meep") err = self.assert_jsonrpc_exception(client.campaigns) self.assertEqual(err.fault, "Fault") self.assertEqual(err.fault_code, 8002) self.assertEqual(err.fault_string, "Meep") def test_campaigns(self): client = self.make_client() self.account_backend.add_success_response("campaigns", [], fixtures.campaigns) self.assertEqual(client.campaigns(), fixtures.campaigns) def test_conversations(self): client = self.make_client() self.account_backend.add_success_response("conversations", ["campaign-1"], fixtures.conversations) self.assertEqual(client.conversations("campaign-1"), fixtures.conversations) def test_channels(self): client = self.make_client() self.account_backend.add_success_response("channels", ["campaign-1"], fixtures.channels) self.assertEqual(client.channels("campaign-1"), fixtures.channels) def test_routers(self): client = self.make_client() self.account_backend.add_success_response("routers", ["campaign-1"], fixtures.routers) self.assertEqual(client.routers("campaign-1"), fixtures.routers) def test_routing_entries(self): client = self.make_client() self.account_backend.add_success_response("routing_entries", ["campaign-1"], fixtures.routing_entries) self.assertEqual(client.routing_entries("campaign-1"), fixtures.routing_entries) def test_routing_table(self): client = self.make_client() self.account_backend.add_success_response("routing_table", ["campaign-1"], fixtures.routing_table) self.assertEqual(client.routing_table("campaign-1"), fixtures.routing_table) def test_update_routing_tabel(self): client = self.make_client() self.account_backend.add_success_response( "update_routing_table", ["campaign-1", fixtures.routing_table], None) self.assertEqual( client.update_routing_table("campaign-1", fixtures.routing_table), None)
class TestAccountApiClient(TestCase): API_URL = "http://example.com/go" AUTH_TOKEN = "auth_token" def setUp(self): self.account_backend = FakeAccountApi("go/", self.AUTH_TOKEN) self.session = TestSession() self.adapter = FakeAccountApiAdapter(self.account_backend) self.simulate_api_up() def simulate_api_down(self): self.session.mount(self.API_URL, TestAdapter("API is down", 500)) def simulate_api_up(self): self.session.mount(self.API_URL, self.adapter) def make_client(self, auth_token=AUTH_TOKEN): return AccountApiClient( auth_token, api_url=self.API_URL, session=self.session) def assert_http_error(self, expected_status, func, *args, **kw): try: func(*args, **kw) except HTTPError as err: self.assertEqual(err.response.status_code, expected_status) else: self.fail( "Expected HTTPError with status %s." % (expected_status,)) def assert_jsonrpc_exception(self, f, *args, **kw): try: f(*args, **kw) except Exception as err: self.assertTrue(isinstance(err, JsonRpcException)) self.assertTrue(isinstance(err.fault, unicode)) self.assertTrue(isinstance(err.fault_code, int)) self.assertTrue(isinstance(err.fault_string, unicode)) return err def test_assert_http_error(self): self.session.mount("http://bad.example.com/", TestAdapter("", 500)) def bad_req(): r = self.session.get("http://bad.example.com/") r.raise_for_status() # Fails when no exception is raised. self.assertRaises( self.failureException, self.assert_http_error, 404, lambda: None) # Fails when an HTTPError with the wrong status code is raised. self.assertRaises( self.failureException, self.assert_http_error, 404, bad_req) # Passes when an HTTPError with the expected status code is raised. self.assert_http_error(500, bad_req) # Non-HTTPError exceptions aren't caught. def raise_error(): raise ValueError() self.assertRaises(ValueError, self.assert_http_error, 404, raise_error) def test_default_session(self): client = AccountApiClient(self.AUTH_TOKEN) self.assertTrue(isinstance(client.session, Session)) def test_default_api_url(self): client = AccountApiClient(self.AUTH_TOKEN) self.assertEqual( client.api_url, "https://go.vumi.org/api/v1/go") def test_auth_failure(self): client = self.make_client(auth_token="bogus_token") self.assert_http_error(403, client.campaigns) def test_jsonrpc_error_handling(self): client = self.make_client() self.account_backend.add_error_response( "campaigns", [], fault="Fault", fault_code=8002, fault_string="Meep") err = self.assert_jsonrpc_exception(client.campaigns) self.assertEqual(err.fault, "Fault") self.assertEqual(err.fault_code, 8002) self.assertEqual(err.fault_string, "Meep") def test_campaigns(self): client = self.make_client() self.account_backend.add_success_response( "campaigns", [], fixtures.campaigns) self.assertEqual(client.campaigns(), fixtures.campaigns) def test_conversations(self): client = self.make_client() self.account_backend.add_success_response( "conversations", ["campaign-1"], fixtures.conversations) self.assertEqual( client.conversations("campaign-1"), fixtures.conversations) def test_channels(self): client = self.make_client() self.account_backend.add_success_response( "channels", ["campaign-1"], fixtures.channels) self.assertEqual( client.channels("campaign-1"), fixtures.channels) def test_routers(self): client = self.make_client() self.account_backend.add_success_response( "routers", ["campaign-1"], fixtures.routers) self.assertEqual( client.routers("campaign-1"), fixtures.routers) def test_routing_entries(self): client = self.make_client() self.account_backend.add_success_response( "routing_entries", ["campaign-1"], fixtures.routing_entries) self.assertEqual( client.routing_entries("campaign-1"), fixtures.routing_entries) def test_routing_table(self): client = self.make_client() self.account_backend.add_success_response( "routing_table", ["campaign-1"], fixtures.routing_table) self.assertEqual( client.routing_table("campaign-1"), fixtures.routing_table) def test_update_routing_tabel(self): client = self.make_client() self.account_backend.add_success_response( "update_routing_table", ["campaign-1", fixtures.routing_table], None) self.assertEqual( client.update_routing_table("campaign-1", fixtures.routing_table), None)
class TestContactsApiClient(TestCase): API_URL = "http://example.com/go" AUTH_TOKEN = "auth_token" MAX_CONTACTS_PER_PAGE = 10 def setUp(self): self.contacts_data = {} self.groups_data = {} self.contacts_backend = FakeContactsApi( "go/", self.AUTH_TOKEN, self.contacts_data, self.groups_data, contacts_limit=self.MAX_CONTACTS_PER_PAGE) self.session = TestSession() self.adapter = FakeContactsApiAdapter(self.contacts_backend) self.simulate_api_up() def simulate_api_down(self): self.session.mount(self.API_URL, TestAdapter("API is down", 500)) def simulate_api_up(self): self.session.mount(self.API_URL, self.adapter) def make_client(self, auth_token=AUTH_TOKEN): return ContactsApiClient( auth_token, api_url=self.API_URL, session=self.session) def make_existing_contact(self, contact_data): existing_contact = make_contact_dict(contact_data) self.contacts_data[existing_contact[u"key"]] = existing_contact return existing_contact def make_existing_group(self, group_data): existing_group = make_group_dict(group_data) self.groups_data[existing_group[u'key']] = existing_group return existing_group def make_n_contacts(self, n, groups=None): contacts = [] for i in range(n): data = { u"msisdn": u"+155564%d" % (i,), u"name": u"Arthur", u"surname": u"of Camelot", } if groups is not None: data["groups"] = groups contacts.append(self.make_existing_contact(data)) return contacts def assert_contacts_equal(self, contacts_a, contacts_b): contacts_a.sort(key=lambda d: d['msisdn']) contacts_b.sort(key=lambda d: d['msisdn']) self.assertEqual(contacts_a, contacts_b) def assert_contact_status(self, contact_key, exists=True): exists_status = (contact_key in self.contacts_data) self.assertEqual(exists_status, exists) def assert_group_status(self, group_key, exists=True): exists_status = (group_key in self.groups_data) self.assertEqual(exists_status, exists) def assert_http_error(self, expected_status, func, *args, **kw): try: func(*args, **kw) except HTTPError as err: self.assertEqual(err.response.status_code, expected_status) else: self.fail( "Expected HTTPError with status %s." % (expected_status,)) def assert_paged_exception(self, f, *args, **kw): try: f(*args, **kw) except Exception as err: self.assertTrue(isinstance(err, PagedException)) self.assertTrue(isinstance(err.cursor, unicode)) self.assertTrue(isinstance(err.error, Exception)) return err def test_assert_http_error(self): self.session.mount("http://bad.example.com/", TestAdapter("", 500)) def bad_req(): r = self.session.get("http://bad.example.com/") r.raise_for_status() # Fails when no exception is raised. self.assertRaises( self.failureException, self.assert_http_error, 404, lambda: None) # Fails when an HTTPError with the wrong status code is raised. self.assertRaises( self.failureException, self.assert_http_error, 404, bad_req) # Passes when an HTTPError with the expected status code is raised. self.assert_http_error(500, bad_req) # Non-HTTPError exceptions aren't caught. def raise_error(): raise ValueError() self.assertRaises(ValueError, self.assert_http_error, 404, raise_error) def test_default_session(self): import requests contacts = ContactsApiClient(self.AUTH_TOKEN) self.assertTrue(isinstance(contacts.session, requests.Session)) def test_default_api_url(self): contacts = ContactsApiClient(self.AUTH_TOKEN) self.assertEqual( contacts.api_url, "https://go.vumi.org/api/v1/go") def test_auth_failure(self): contacts = self.make_client(auth_token="bogus_token") self.assert_http_error(403, contacts.get_contact, "foo") def test_contacts_single_page(self): [expected_contact] = self.make_n_contacts(1) contacts_api = self.make_client() [contact] = list(contacts_api.contacts()) self.assertEqual(contact, expected_contact) def test_contacts_no_results(self): contacts_api = self.make_client() contacts = list(contacts_api.contacts()) self.assertEqual(contacts, []) def test_contacts_multiple_pages(self): expected_contacts = self.make_n_contacts( self.MAX_CONTACTS_PER_PAGE + 1) contacts_api = self.make_client() contacts = list(contacts_api.contacts()) self.assert_contacts_equal(contacts, expected_contacts) def test_contacts_multiple_pages_with_cursor(self): expected_contacts = self.make_n_contacts( self.MAX_CONTACTS_PER_PAGE + 1) contacts_api = self.make_client() first_page = contacts_api._api_request("GET", "contacts", "") cursor = first_page['cursor'] contacts = list(contacts_api.contacts(start_cursor=cursor)) contacts.extend(first_page['data']) self.assert_contacts_equal(contacts, expected_contacts) def test_contacts_multiple_pages_with_failure(self): expected_contacts = self.make_n_contacts( self.MAX_CONTACTS_PER_PAGE + 1) contacts_api = self.make_client() it = contacts_api.contacts() contacts = [it.next() for _ in range(self.MAX_CONTACTS_PER_PAGE)] self.simulate_api_down() err = self.assert_paged_exception(it.next) self.simulate_api_up() [last_contact] = list(contacts_api.contacts(start_cursor=err.cursor)) self.assert_contacts_equal( contacts + [last_contact], expected_contacts) def test_create_contact(self): contacts = self.make_client() contact_data = { u"msisdn": u"+15556483", u"name": u"Arthur", u"surname": u"of Camelot", } contact = contacts.create_contact(contact_data) expected_contact = make_contact_dict(contact_data) # The key is generated for us. expected_contact[u"key"] = contact[u"key"] self.assertEqual(contact, expected_contact) self.assert_contact_status(contact[u"key"], exists=True) def test_create_contact_with_extras(self): contacts = self.make_client() contact_data = { u"msisdn": u"+15556483", u"name": u"Arthur", u"surname": u"of Camelot", u"extra": { u"quest": u"Grail", u"sidekick": u"Percy", }, } contact = contacts.create_contact(contact_data) expected_contact = make_contact_dict(contact_data) # The key is generated for us. expected_contact[u"key"] = contact[u"key"] self.assertEqual(contact, expected_contact) self.assert_contact_status(contact[u"key"], exists=True) def test_create_contact_with_key(self): contacts = self.make_client() contact_data = { u"key": u"foo", u"msisdn": u"+15556483", u"name": u"Arthur", u"surname": u"of Camelot", } self.assert_http_error(400, contacts.create_contact, contact_data) self.assert_contact_status(u"foo", exists=False) def test_get_contact(self): contacts = self.make_client() existing_contact = self.make_existing_contact({ u"msisdn": u"+15556483", u"name": u"Arthur", u"surname": u"of Camelot", }) contact = contacts.get_contact(existing_contact[u"key"]) self.assertEqual(contact, existing_contact) def test_get_contact_with_extras(self): contacts = self.make_client() existing_contact = self.make_existing_contact({ u"msisdn": u"+15556483", u"name": u"Arthur", u"surname": u"of Camelot", u"extra": { u"quest": u"Grail", u"sidekick": u"Percy", }, }) contact = contacts.get_contact(existing_contact[u"key"]) self.assertEqual(contact, existing_contact) def test_get_missing_contact(self): contacts = self.make_client() self.assert_http_error(404, contacts.get_contact, "foo") def test_get_contact_from_field(self): contacts = self.make_client() existing_contact = self.make_existing_contact({ u"msisdn": u"+15556483", u"name": u"Arthur", u"surname": u"of Camelot", }) contact = contacts.get_contact(msisdn='+15556483') self.assertEqual(contact, existing_contact) def test_get_contact_from_field_missing(self): contacts = self.make_client() self.make_existing_contact({ u"msisdn": u"+15556483", u"name": u"Arthur", u"surname": u"of Camelot", }) self.assert_http_error( 400, contacts.get_contact, msisdn='+12345') def test_update_contact(self): contacts = self.make_client() existing_contact = self.make_existing_contact({ u"msisdn": u"+15556483", u"name": u"Arthur", u"surname": u"of Camelot", }) new_contact = existing_contact.copy() new_contact[u"surname"] = u"Pendragon" contact = contacts.update_contact( existing_contact[u"key"], {u"surname": u"Pendragon"}) self.assertEqual(contact, new_contact) def test_update_contact_with_extras(self): contacts = self.make_client() existing_contact = self.make_existing_contact({ u"msisdn": u"+15556483", u"name": u"Arthur", u"surname": u"of Camelot", u"extra": { u"quest": u"Grail", u"sidekick": u"Percy", }, }) new_contact = existing_contact.copy() new_contact[u"surname"] = u"Pendragon" new_contact[u"extra"] = { u"quest": u"lunch", u"knight": u"Lancelot", } contact = contacts.update_contact(existing_contact[u"key"], { u"surname": u"Pendragon", u"extra": { u"quest": u"lunch", u"knight": u"Lancelot", }, }) self.assertEqual(contact, new_contact) def test_update_missing_contact(self): contacts = self.make_client() self.assert_http_error(404, contacts.update_contact, "foo", {}) def test_delete_contact(self): contacts = self.make_client() existing_contact = self.make_existing_contact({ u"msisdn": u"+15556483", u"name": u"Arthur", u"surname": u"of Camelot", }) self.assert_contact_status(existing_contact[u"key"], exists=True) contact = contacts.delete_contact(existing_contact[u"key"]) self.assertEqual(contact, existing_contact) self.assert_contact_status(existing_contact[u"key"], exists=False) def test_delete_missing_contact(self): contacts = self.make_client() self.assert_http_error(404, contacts.delete_contact, "foo") def test_create_group(self): client = self.make_client() group_data = { u'name': u'Bob', } group = client.create_group(group_data) expected_group = make_group_dict(group_data) # The key is generated for us. expected_group[u'key'] = group[u'key'] self.assertEqual(group, expected_group) self.assert_group_status(group[u'key'], exists=True) def test_create_smart_group(self): client = self.make_client() group_data = { u'name': u'Bob', u'query': u'test-query', } group = client.create_group(group_data) expected_group = make_group_dict(group_data) # The key is generated for us expected_group[u'key'] = group[u'key'] self.assertEqual(group, expected_group) self.assert_group_status(group[u'key'], exists=True) def test_create_group_with_key(self): client = self.make_client() group_data = { u'key': u'foo', u'name': u'Bob', u'query': u'test-query', } self.assert_http_error(400, client.create_group, group_data) def test_get_group(self): client = self.make_client() existing_group = self.make_existing_group({ u'name': 'Bob', }) group = client.get_group(existing_group[u'key']) self.assertEqual(group, existing_group) def test_get_smart_group(self): client = self.make_client() existing_group = self.make_existing_group({ u'name': 'Bob', u'query': 'test-query', }) group = client.get_group(existing_group[u'key']) self.assertEqual(group, existing_group) def test_get_missing_group(self): client = self.make_client() self.assert_http_error(404, client.get_group, 'foo') def test_update_group(self): client = self.make_client() existing_group = self.make_existing_group({ u'name': u'Bob', }) new_group = existing_group.copy() new_group[u'name'] = u'Susan' group = client.update_group(existing_group[u'key'], {'name': 'Susan'}) self.assertEqual(existing_group, group) self.assertEqual(group, new_group) def test_update_smart_group(self): client = self.make_client() existing_group = self.make_existing_group({ u'name': u'Bob', u'query': u'test-query', }) new_group = existing_group.copy() new_group[u'query'] = u'another-query' group = client.update_group(existing_group[u'key'], {'query': 'another-query'}) self.assertEqual(existing_group, group) self.assertEqual(group, new_group) def test_update_missing_group(self): client = self.make_client() self.assert_http_error(404, client.update_group, 'foo', {}) def test_delete_group(self): client = self.make_client() existing_group = self.make_existing_group({ u'name': u'Bob' }) self.assert_group_status(existing_group[u'key'], exists=True) group = client.delete_group(existing_group[u'key']) self.assertEqual(existing_group, group) self.assert_group_status(group[u'key'], exists=False) def test_delete_missing_group(self): client = self.make_client() self.assert_http_error(404, client.delete_group, 'foo') def test_group_contacts_multiple_pages_with_cursor(self): self.make_existing_group({ u'name': 'key', }) expected_contacts = self.make_n_contacts( self.MAX_CONTACTS_PER_PAGE + 1, groups=["key"]) client = self.make_client() first_page = client._api_request("GET", "groups/key", "contacts") cursor = first_page['cursor'] contacts = list(client.group_contacts(group_key="key", start_cursor=cursor)) contacts.extend(first_page['data']) contacts.sort(key=lambda d: d['msisdn']) expected_contacts.sort(key=lambda d: d['msisdn']) self.assertEqual(contacts, expected_contacts) def test_group_contacts_multiple_pages(self): self.make_existing_group({ u'name': 'key', }) self.make_existing_group({ u'name': 'diffkey', }) expected_contacts = self.make_n_contacts( self.MAX_CONTACTS_PER_PAGE + 1, groups=["key"]) self.make_existing_contact({ u"msisdn": u"+1234567", u"name": u"Nancy", u"surname": u"of Camelot", u"groups": ["diffkey"], }) client = self.make_client() contacts = list(client.group_contacts("key")) self.assert_contacts_equal(contacts, expected_contacts) def test_group_contacts_multiple_pages_with_failure(self): self.make_existing_group({ u'name': 'key', }) self.make_existing_group({ u'name': 'diffkey', }) expected_contacts = self.make_n_contacts( self.MAX_CONTACTS_PER_PAGE + 1, groups=["key"]) self.make_existing_contact({ u"msisdn": u"+1234567", u"name": u"Nancy", u"surname": u"of Camelot", u"groups": ["diffkey"], }) contacts_api = self.make_client() it = contacts_api.group_contacts("key") contacts = [it.next() for _ in range(self.MAX_CONTACTS_PER_PAGE)] self.simulate_api_down() err = self.assert_paged_exception(it.next) self.simulate_api_up() [last_contact] = list(contacts_api.group_contacts( "key", start_cursor=err.cursor)) self.assert_contacts_equal( contacts + [last_contact], expected_contacts) def test_group_contacts_none_found(self): self.make_existing_group({ u'name': 'key', }) self.make_existing_group({ u'name': 'diffkey', }) self.make_n_contacts( self.MAX_CONTACTS_PER_PAGE + 1, groups=["diffkey"]) client = self.make_client() contacts = list(client.group_contacts("key")) self.assert_contacts_equal(contacts, [])
class TestContentStoreApiClient(TestCase): API_URL = "http://example.com/contentstore" AUTH_TOKEN = "auth_token" def setUp(self): self.messageset_data = {} self.schedule_data = {} self.message_data = {} self.binary_content_data = {} self.contentstore_backend = FakeContentStoreApi( "contentstore/", self.AUTH_TOKEN, messageset_data=self.messageset_data, schedule_data=self.schedule_data, message_data=self.message_data, binary_content_data=self.binary_content_data) self.session = TestSession() adapter = FakeContentStoreApiAdapter(self.contentstore_backend) self.session.mount(self.API_URL, adapter) self.client = self.make_client() def make_client(self, auth_token=AUTH_TOKEN): return ContentStoreApiClient( auth_token, api_url=self.API_URL, session=self.session) def make_existing_messageset(self, messageset_data): existing_messageset = make_messageset_dict(messageset_data) self.messageset_data[existing_messageset[u"id"]] = existing_messageset return existing_messageset def make_existing_message(self, message_data): existing_message = make_message_dict(message_data) self.message_data[existing_message[u"id"]] = existing_message return existing_message def make_existing_schedule(self, schedule_data): existing_schedule = make_schedule_dict(schedule_data) self.schedule_data[existing_schedule[u"id"]] = existing_schedule return existing_schedule def assert_messageset_status(self, messageset_id, exists=True): exists_status = (messageset_id in self.messageset_data) self.assertEqual(exists_status, exists) def assert_http_error(self, expected_status, func, *args, **kw): try: func(*args, **kw) except HTTPError as err: self.assertEqual(err.response.status_code, expected_status) else: self.fail( "Expected HTTPError with status %s." % (expected_status,)) def test_assert_http_error(self): self.session.mount("http://bad.example.com/", TestAdapter("", 500)) def bad_req(): r = self.session.get("http://bad.example.com/") r.raise_for_status() # Fails when no exception is raised. self.assertRaises( self.failureException, self.assert_http_error, 404, lambda: None) # Fails when an HTTPError with the wrong status code is raised. self.assertRaises( self.failureException, self.assert_http_error, 404, bad_req) # Passes when an HTTPError with the expected status code is raised. self.assert_http_error(500, bad_req) # Non-HTTPError exceptions aren't caught. def raise_error(): raise ValueError() self.assertRaises(ValueError, self.assert_http_error, 404, raise_error) def test_default_session(self): import requests contentstore = ContentStoreApiClient(self.AUTH_TOKEN) self.assertTrue(isinstance(contentstore.session, requests.Session)) def test_default_api_url(self): contentstore = ContentStoreApiClient(self.AUTH_TOKEN) self.assertEqual( contentstore.api_url, "http://testserver/contentstore") def test_auth_failure(self): contentstore = self.make_client(auth_token="bogus_token") self.assert_http_error(403, contentstore.get_messagesets) def test_get_messageset(self): expected_messageset = self.make_existing_messageset({ u"short_name": u"Full Set", u"notes": u"A full set of messages.", u"default_schedule": 1 }) [messageset] = list(self.client.get_messagesets()) self.assertEqual(messageset, expected_messageset) def test_create_messageset(self): new_messageset = self.client.create_messageset({ u"short_name": u"Full Set1", u"notes": u"A full and new set of messages.", u"default_schedule": 1 }) [messageset] = list(self.client.get_messagesets()) self.assertEqual( messageset["short_name"], new_messageset["short_name"]) self.assertEqual( messageset["notes"], new_messageset["notes"]) self.assertEqual( messageset["default_schedule"], new_messageset["default_schedule"]) def test_delete_messageset(self): new_messageset = self.make_existing_messageset({ u"short_name": u"Full Set", u"notes": u"A full set of messages that will go.", u"default_schedule": 1 }) [messageset] = list(self.client.get_messagesets()) self.assertEqual(messageset, new_messageset) self.client.delete_messageset(new_messageset["id"]) messageset = list(self.client.get_messagesets()) self.assertEqual(messageset, []) def test_get_message(self): expected_message = self.make_existing_message({ "messageset": 1, "sequence_number": 2, "lang": "afr_ZA", "text_content": "Message two" }) [message] = list(self.client.get_messages()) self.assertEqual(message, expected_message) def test_get_message_content(self): expected_message = self.make_existing_message({ "messageset": 1, "sequence_number": 2, "lang": "afr_ZA", "text_content": "Message two" }) message = self.client.get_message_content(expected_message[u"id"]) self.assertEqual(message, expected_message) def test_get_messageset_messages(self): new_messageset = self.client.create_messageset({ u"short_name": u"Full Set1", u"notes": u"A full and new set of messages.", u"default_schedule": 1 }) messageset_id = new_messageset["id"] expected_message = self.make_existing_message({ "messageset": messageset_id, "sequence_number": 2, "lang": "afr_ZA", "text_content": "Message two" }) expected_message2 = self.make_existing_message({ "messageset": messageset_id, "sequence_number": 1, "lang": "afr_ZA", "text_content": "Message one" }) messageset_messages = self.client.get_messageset_messages( messageset_id) self.assertEqual(len(messageset_messages["messages"]), 2) # should be sorted by sequence_number self.assertEqual(messageset_messages["messages"][0]["id"], expected_message2["id"]) self.assertEqual(messageset_messages["messages"][1]["id"], expected_message["id"]) def test_create_message(self): new_message = self.client.create_message({ "messageset": 1, "sequence_number": 2, "lang": "afr_ZA", "text_content": "Message two" }) [message] = list(self.client.get_messages()) self.assertEqual(message["text_content"], new_message["text_content"]) self.assertEqual(message["sequence_number"], new_message["sequence_number"]) self.assertEqual(message["messageset"], new_message["messageset"]) self.assertEqual(message["lang"], new_message["lang"]) def test_get_schedule(self): expected_schedule = self.make_existing_schedule({ "minute": "1", "hour": "2", "day_of_week": "3", "day_of_month": "4", "month_of_year": "5", }) [schedule] = list(self.client.get_schedules()) self.assertEqual(schedule, expected_schedule) def test_create_schedule(self): new_schedule = self.client.create_schedule({ "minute": "1", "hour": "2", "day_of_week": "3", "day_of_month": "4", "month_of_year": "5", }) [schedule] = list(self.client.get_schedules()) self.assertEqual(schedule["minute"], new_schedule["minute"]) self.assertEqual(schedule["hour"], new_schedule["hour"]) self.assertEqual(schedule["day_of_week"], new_schedule["day_of_week"]) self.assertEqual(schedule["day_of_month"], new_schedule["day_of_month"]) self.assertEqual(schedule["month_of_year"], new_schedule["month_of_year"])
class TestContactsApiClient(TestCase): API_URL = "http://example.com/go" AUTH_TOKEN = "auth_token" MAX_CONTACTS_PER_PAGE = 10 def setUp(self): self.contacts_data = {} self.groups_data = {} self.contacts_backend = FakeContactsApi( "go/", self.AUTH_TOKEN, self.contacts_data, self.groups_data, contacts_limit=self.MAX_CONTACTS_PER_PAGE) self.session = TestSession() self.adapter = FakeContactsApiAdapter(self.contacts_backend) self.simulate_api_up() def simulate_api_down(self): self.session.mount(self.API_URL, TestAdapter("API is down", 500)) def simulate_api_up(self): self.session.mount(self.API_URL, self.adapter) def make_client(self, auth_token=AUTH_TOKEN): return ContactsApiClient(auth_token, api_url=self.API_URL, session=self.session) def make_existing_contact(self, contact_data): existing_contact = make_contact_dict(contact_data) self.contacts_data[existing_contact[u"key"]] = existing_contact return existing_contact def make_existing_group(self, group_data): existing_group = make_group_dict(group_data) self.groups_data[existing_group[u'key']] = existing_group return existing_group def make_n_contacts(self, n, groups=None): contacts = [] for i in range(n): data = { u"msisdn": u"+155564%d" % (i, ), u"name": u"Arthur", u"surname": u"of Camelot", } if groups is not None: data["groups"] = groups contacts.append(self.make_existing_contact(data)) return contacts def assert_contacts_equal(self, contacts_a, contacts_b): contacts_a.sort(key=lambda d: d['msisdn']) contacts_b.sort(key=lambda d: d['msisdn']) self.assertEqual(contacts_a, contacts_b) def assert_contact_status(self, contact_key, exists=True): exists_status = (contact_key in self.contacts_data) self.assertEqual(exists_status, exists) def assert_group_status(self, group_key, exists=True): exists_status = (group_key in self.groups_data) self.assertEqual(exists_status, exists) def assert_http_error(self, expected_status, func, *args, **kw): try: func(*args, **kw) except HTTPError as err: self.assertEqual(err.response.status_code, expected_status) else: self.fail("Expected HTTPError with status %s." % (expected_status, )) def assert_paged_exception(self, f, *args, **kw): try: f(*args, **kw) except Exception as err: self.assertTrue(isinstance(err, PagedException)) self.assertTrue(isinstance(err.cursor, unicode)) self.assertTrue(isinstance(err.error, Exception)) return err def test_assert_http_error(self): self.session.mount("http://bad.example.com/", TestAdapter("", 500)) def bad_req(): r = self.session.get("http://bad.example.com/") r.raise_for_status() # Fails when no exception is raised. self.assertRaises(self.failureException, self.assert_http_error, 404, lambda: None) # Fails when an HTTPError with the wrong status code is raised. self.assertRaises(self.failureException, self.assert_http_error, 404, bad_req) # Passes when an HTTPError with the expected status code is raised. self.assert_http_error(500, bad_req) # Non-HTTPError exceptions aren't caught. def raise_error(): raise ValueError() self.assertRaises(ValueError, self.assert_http_error, 404, raise_error) def test_default_session(self): import requests contacts = ContactsApiClient(self.AUTH_TOKEN) self.assertTrue(isinstance(contacts.session, requests.Session)) def test_default_api_url(self): contacts = ContactsApiClient(self.AUTH_TOKEN) self.assertEqual(contacts.api_url, "https://go.vumi.org/api/v1/go") def test_auth_failure(self): contacts = self.make_client(auth_token="bogus_token") self.assert_http_error(403, contacts.get_contact, "foo") def test_contacts_single_page(self): [expected_contact] = self.make_n_contacts(1) contacts_api = self.make_client() [contact] = list(contacts_api.contacts()) self.assertEqual(contact, expected_contact) def test_contacts_no_results(self): contacts_api = self.make_client() contacts = list(contacts_api.contacts()) self.assertEqual(contacts, []) def test_contacts_multiple_pages(self): expected_contacts = self.make_n_contacts(self.MAX_CONTACTS_PER_PAGE + 1) contacts_api = self.make_client() contacts = list(contacts_api.contacts()) self.assert_contacts_equal(contacts, expected_contacts) def test_contacts_multiple_pages_with_cursor(self): expected_contacts = self.make_n_contacts(self.MAX_CONTACTS_PER_PAGE + 1) contacts_api = self.make_client() first_page = contacts_api._api_request("GET", "contacts", "") cursor = first_page['cursor'] contacts = list(contacts_api.contacts(start_cursor=cursor)) contacts.extend(first_page['data']) self.assert_contacts_equal(contacts, expected_contacts) def test_contacts_multiple_pages_with_failure(self): expected_contacts = self.make_n_contacts(self.MAX_CONTACTS_PER_PAGE + 1) contacts_api = self.make_client() it = contacts_api.contacts() contacts = [it.next() for _ in range(self.MAX_CONTACTS_PER_PAGE)] self.simulate_api_down() err = self.assert_paged_exception(it.next) self.simulate_api_up() [last_contact] = list(contacts_api.contacts(start_cursor=err.cursor)) self.assert_contacts_equal(contacts + [last_contact], expected_contacts) def test_create_contact(self): contacts = self.make_client() contact_data = { u"msisdn": u"+15556483", u"name": u"Arthur", u"surname": u"of Camelot", } contact = contacts.create_contact(contact_data) expected_contact = make_contact_dict(contact_data) # The key is generated for us. expected_contact[u"key"] = contact[u"key"] self.assertEqual(contact, expected_contact) self.assert_contact_status(contact[u"key"], exists=True) def test_create_contact_with_extras(self): contacts = self.make_client() contact_data = { u"msisdn": u"+15556483", u"name": u"Arthur", u"surname": u"of Camelot", u"extra": { u"quest": u"Grail", u"sidekick": u"Percy", }, } contact = contacts.create_contact(contact_data) expected_contact = make_contact_dict(contact_data) # The key is generated for us. expected_contact[u"key"] = contact[u"key"] self.assertEqual(contact, expected_contact) self.assert_contact_status(contact[u"key"], exists=True) def test_create_contact_with_key(self): contacts = self.make_client() contact_data = { u"key": u"foo", u"msisdn": u"+15556483", u"name": u"Arthur", u"surname": u"of Camelot", } self.assert_http_error(400, contacts.create_contact, contact_data) self.assert_contact_status(u"foo", exists=False) def test_get_contact(self): contacts = self.make_client() existing_contact = self.make_existing_contact({ u"msisdn": u"+15556483", u"name": u"Arthur", u"surname": u"of Camelot", }) contact = contacts.get_contact(existing_contact[u"key"]) self.assertEqual(contact, existing_contact) def test_get_contact_with_extras(self): contacts = self.make_client() existing_contact = self.make_existing_contact({ u"msisdn": u"+15556483", u"name": u"Arthur", u"surname": u"of Camelot", u"extra": { u"quest": u"Grail", u"sidekick": u"Percy", }, }) contact = contacts.get_contact(existing_contact[u"key"]) self.assertEqual(contact, existing_contact) def test_get_missing_contact(self): contacts = self.make_client() self.assert_http_error(404, contacts.get_contact, "foo") def test_get_contact_from_field(self): contacts = self.make_client() existing_contact = self.make_existing_contact({ u"msisdn": u"+15556483", u"name": u"Arthur", u"surname": u"of Camelot", }) contact = contacts.get_contact(msisdn='+15556483') self.assertEqual(contact, existing_contact) def test_get_contact_from_field_missing(self): contacts = self.make_client() self.make_existing_contact({ u"msisdn": u"+15556483", u"name": u"Arthur", u"surname": u"of Camelot", }) self.assert_http_error(400, contacts.get_contact, msisdn='+12345') def test_update_contact(self): contacts = self.make_client() existing_contact = self.make_existing_contact({ u"msisdn": u"+15556483", u"name": u"Arthur", u"surname": u"of Camelot", }) new_contact = existing_contact.copy() new_contact[u"surname"] = u"Pendragon" contact = contacts.update_contact(existing_contact[u"key"], {u"surname": u"Pendragon"}) self.assertEqual(contact, new_contact) def test_update_contact_with_extras(self): contacts = self.make_client() existing_contact = self.make_existing_contact({ u"msisdn": u"+15556483", u"name": u"Arthur", u"surname": u"of Camelot", u"extra": { u"quest": u"Grail", u"sidekick": u"Percy", }, }) new_contact = existing_contact.copy() new_contact[u"surname"] = u"Pendragon" new_contact[u"extra"] = { u"quest": u"lunch", u"knight": u"Lancelot", } contact = contacts.update_contact( existing_contact[u"key"], { u"surname": u"Pendragon", u"extra": { u"quest": u"lunch", u"knight": u"Lancelot", }, }) self.assertEqual(contact, new_contact) def test_update_missing_contact(self): contacts = self.make_client() self.assert_http_error(404, contacts.update_contact, "foo", {}) def test_delete_contact(self): contacts = self.make_client() existing_contact = self.make_existing_contact({ u"msisdn": u"+15556483", u"name": u"Arthur", u"surname": u"of Camelot", }) self.assert_contact_status(existing_contact[u"key"], exists=True) contact = contacts.delete_contact(existing_contact[u"key"]) self.assertEqual(contact, existing_contact) self.assert_contact_status(existing_contact[u"key"], exists=False) def test_delete_missing_contact(self): contacts = self.make_client() self.assert_http_error(404, contacts.delete_contact, "foo") def test_create_group(self): client = self.make_client() group_data = { u'name': u'Bob', } group = client.create_group(group_data) expected_group = make_group_dict(group_data) # The key is generated for us. expected_group[u'key'] = group[u'key'] self.assertEqual(group, expected_group) self.assert_group_status(group[u'key'], exists=True) def test_create_smart_group(self): client = self.make_client() group_data = { u'name': u'Bob', u'query': u'test-query', } group = client.create_group(group_data) expected_group = make_group_dict(group_data) # The key is generated for us expected_group[u'key'] = group[u'key'] self.assertEqual(group, expected_group) self.assert_group_status(group[u'key'], exists=True) def test_create_group_with_key(self): client = self.make_client() group_data = { u'key': u'foo', u'name': u'Bob', u'query': u'test-query', } self.assert_http_error(400, client.create_group, group_data) def test_get_group(self): client = self.make_client() existing_group = self.make_existing_group({ u'name': 'Bob', }) group = client.get_group(existing_group[u'key']) self.assertEqual(group, existing_group) def test_get_smart_group(self): client = self.make_client() existing_group = self.make_existing_group({ u'name': 'Bob', u'query': 'test-query', }) group = client.get_group(existing_group[u'key']) self.assertEqual(group, existing_group) def test_get_missing_group(self): client = self.make_client() self.assert_http_error(404, client.get_group, 'foo') def test_update_group(self): client = self.make_client() existing_group = self.make_existing_group({ u'name': u'Bob', }) new_group = existing_group.copy() new_group[u'name'] = u'Susan' group = client.update_group(existing_group[u'key'], {'name': 'Susan'}) self.assertEqual(existing_group, group) self.assertEqual(group, new_group) def test_update_smart_group(self): client = self.make_client() existing_group = self.make_existing_group({ u'name': u'Bob', u'query': u'test-query', }) new_group = existing_group.copy() new_group[u'query'] = u'another-query' group = client.update_group(existing_group[u'key'], {'query': 'another-query'}) self.assertEqual(existing_group, group) self.assertEqual(group, new_group) def test_update_missing_group(self): client = self.make_client() self.assert_http_error(404, client.update_group, 'foo', {}) def test_delete_group(self): client = self.make_client() existing_group = self.make_existing_group({u'name': u'Bob'}) self.assert_group_status(existing_group[u'key'], exists=True) group = client.delete_group(existing_group[u'key']) self.assertEqual(existing_group, group) self.assert_group_status(group[u'key'], exists=False) def test_delete_missing_group(self): client = self.make_client() self.assert_http_error(404, client.delete_group, 'foo') def test_group_contacts_multiple_pages_with_cursor(self): self.make_existing_group({ u'name': 'key', }) expected_contacts = self.make_n_contacts(self.MAX_CONTACTS_PER_PAGE + 1, groups=["key"]) client = self.make_client() first_page = client._api_request("GET", "groups/key", "contacts") cursor = first_page['cursor'] contacts = list( client.group_contacts(group_key="key", start_cursor=cursor)) contacts.extend(first_page['data']) contacts.sort(key=lambda d: d['msisdn']) expected_contacts.sort(key=lambda d: d['msisdn']) self.assertEqual(contacts, expected_contacts) def test_group_contacts_multiple_pages(self): self.make_existing_group({ u'name': 'key', }) self.make_existing_group({ u'name': 'diffkey', }) expected_contacts = self.make_n_contacts(self.MAX_CONTACTS_PER_PAGE + 1, groups=["key"]) self.make_existing_contact({ u"msisdn": u"+1234567", u"name": u"Nancy", u"surname": u"of Camelot", u"groups": ["diffkey"], }) client = self.make_client() contacts = list(client.group_contacts("key")) self.assert_contacts_equal(contacts, expected_contacts) def test_group_contacts_multiple_pages_with_failure(self): self.make_existing_group({ u'name': 'key', }) self.make_existing_group({ u'name': 'diffkey', }) expected_contacts = self.make_n_contacts(self.MAX_CONTACTS_PER_PAGE + 1, groups=["key"]) self.make_existing_contact({ u"msisdn": u"+1234567", u"name": u"Nancy", u"surname": u"of Camelot", u"groups": ["diffkey"], }) contacts_api = self.make_client() it = contacts_api.group_contacts("key") contacts = [it.next() for _ in range(self.MAX_CONTACTS_PER_PAGE)] self.simulate_api_down() err = self.assert_paged_exception(it.next) self.simulate_api_up() [last_contact ] = list(contacts_api.group_contacts("key", start_cursor=err.cursor)) self.assert_contacts_equal(contacts + [last_contact], expected_contacts) def test_group_contacts_none_found(self): self.make_existing_group({ u'name': 'key', }) self.make_existing_group({ u'name': 'diffkey', }) self.make_n_contacts(self.MAX_CONTACTS_PER_PAGE + 1, groups=["diffkey"]) client = self.make_client() contacts = list(client.group_contacts("key")) self.assert_contacts_equal(contacts, [])
class TestContentStoreApiClient(TestCase): API_URL = "http://example.com/contentstore" AUTH_TOKEN = "auth_token" def setUp(self): self.messageset_data = {} self.schedule_data = {} self.message_data = {} self.binary_content_data = {} self.contentstore_backend = FakeContentStoreApi( "contentstore/", self.AUTH_TOKEN, messageset_data=self.messageset_data, schedule_data=self.schedule_data, message_data=self.message_data, binary_content_data=self.binary_content_data) self.session = TestSession() adapter = FakeContentStoreApiAdapter(self.contentstore_backend) self.session.mount(self.API_URL, adapter) self.client = self.make_client() def make_client(self, auth_token=AUTH_TOKEN): return ContentStoreApiClient(auth_token, api_url=self.API_URL, session=self.session) def make_existing_messageset(self, messageset_data): existing_messageset = make_messageset_dict(messageset_data) self.messageset_data[existing_messageset[u"id"]] = existing_messageset return existing_messageset def make_existing_message(self, message_data): existing_message = make_message_dict(message_data) self.message_data[existing_message[u"id"]] = existing_message return existing_message def make_existing_schedule(self, schedule_data): existing_schedule = make_schedule_dict(schedule_data) self.schedule_data[existing_schedule[u"id"]] = existing_schedule return existing_schedule def assert_messageset_status(self, messageset_id, exists=True): exists_status = (messageset_id in self.messageset_data) self.assertEqual(exists_status, exists) def assert_http_error(self, expected_status, func, *args, **kw): try: func(*args, **kw) except HTTPError as err: self.assertEqual(err.response.status_code, expected_status) else: self.fail("Expected HTTPError with status %s." % (expected_status, )) def test_assert_http_error(self): self.session.mount("http://bad.example.com/", TestAdapter("", 500)) def bad_req(): r = self.session.get("http://bad.example.com/") r.raise_for_status() # Fails when no exception is raised. self.assertRaises(self.failureException, self.assert_http_error, 404, lambda: None) # Fails when an HTTPError with the wrong status code is raised. self.assertRaises(self.failureException, self.assert_http_error, 404, bad_req) # Passes when an HTTPError with the expected status code is raised. self.assert_http_error(500, bad_req) # Non-HTTPError exceptions aren't caught. def raise_error(): raise ValueError() self.assertRaises(ValueError, self.assert_http_error, 404, raise_error) def test_default_session(self): import requests contentstore = ContentStoreApiClient(self.AUTH_TOKEN) self.assertTrue(isinstance(contentstore.session, requests.Session)) def test_default_api_url(self): contentstore = ContentStoreApiClient(self.AUTH_TOKEN) self.assertEqual(contentstore.api_url, "http://testserver/contentstore") def test_auth_failure(self): contentstore = self.make_client(auth_token="bogus_token") self.assert_http_error(403, contentstore.get_messagesets) def test_get_messageset(self): expected_messageset = self.make_existing_messageset({ u"short_name": u"Full Set", u"notes": u"A full set of messages.", u"default_schedule": 1 }) [messageset] = list(self.client.get_messagesets()) self.assertEqual(messageset, expected_messageset) def test_create_messageset(self): new_messageset = self.client.create_messageset({ u"short_name": u"Full Set1", u"notes": u"A full and new set of messages.", u"default_schedule": 1 }) [messageset] = list(self.client.get_messagesets()) self.assertEqual(messageset["short_name"], new_messageset["short_name"]) self.assertEqual(messageset["notes"], new_messageset["notes"]) self.assertEqual(messageset["default_schedule"], new_messageset["default_schedule"]) def test_delete_messageset(self): new_messageset = self.make_existing_messageset({ u"short_name": u"Full Set", u"notes": u"A full set of messages that will go.", u"default_schedule": 1 }) [messageset] = list(self.client.get_messagesets()) self.assertEqual(messageset, new_messageset) self.client.delete_messageset(new_messageset["id"]) messageset = list(self.client.get_messagesets()) self.assertEqual(messageset, []) def test_get_message(self): expected_message = self.make_existing_message({ "messageset": 1, "sequence_number": 2, "lang": "afr_ZA", "text_content": "Message two" }) [message] = list(self.client.get_messages()) self.assertEqual(message, expected_message) def test_get_message_content(self): expected_message = self.make_existing_message({ "messageset": 1, "sequence_number": 2, "lang": "afr_ZA", "text_content": "Message two" }) message = self.client.get_message_content(expected_message[u"id"]) self.assertEqual(message, expected_message) def test_get_messageset_messages(self): new_messageset = self.client.create_messageset({ u"short_name": u"Full Set1", u"notes": u"A full and new set of messages.", u"default_schedule": 1 }) messageset_id = new_messageset["id"] expected_message = self.make_existing_message({ "messageset": messageset_id, "sequence_number": 2, "lang": "afr_ZA", "text_content": "Message two" }) expected_message2 = self.make_existing_message({ "messageset": messageset_id, "sequence_number": 1, "lang": "afr_ZA", "text_content": "Message one" }) messageset_messages = self.client.get_messageset_messages( messageset_id) self.assertEqual(len(messageset_messages["messages"]), 2) # should be sorted by sequence_number self.assertEqual(messageset_messages["messages"][0]["id"], expected_message2["id"]) self.assertEqual(messageset_messages["messages"][1]["id"], expected_message["id"]) def test_create_message(self): new_message = self.client.create_message({ "messageset": 1, "sequence_number": 2, "lang": "afr_ZA", "text_content": "Message two" }) [message] = list(self.client.get_messages()) self.assertEqual(message["text_content"], new_message["text_content"]) self.assertEqual(message["sequence_number"], new_message["sequence_number"]) self.assertEqual(message["messageset"], new_message["messageset"]) self.assertEqual(message["lang"], new_message["lang"]) def test_get_schedule(self): expected_schedule = self.make_existing_schedule({ "minute": "1", "hour": "2", "day_of_week": "3", "day_of_month": "4", "month_of_year": "5", }) [schedule] = list(self.client.get_schedules()) self.assertEqual(schedule, expected_schedule) def test_create_schedule(self): new_schedule = self.client.create_schedule({ "minute": "1", "hour": "2", "day_of_week": "3", "day_of_month": "4", "month_of_year": "5", }) [schedule] = list(self.client.get_schedules()) self.assertEqual(schedule["minute"], new_schedule["minute"]) self.assertEqual(schedule["hour"], new_schedule["hour"]) self.assertEqual(schedule["day_of_week"], new_schedule["day_of_week"]) self.assertEqual(schedule["day_of_month"], new_schedule["day_of_month"]) self.assertEqual(schedule["month_of_year"], new_schedule["month_of_year"])