diff --git a/aweber_api/collection.py b/aweber_api/collection.py index 20d7538..5073a68 100644 --- a/aweber_api/collection.py +++ b/aweber_api/collection.py @@ -3,6 +3,8 @@ from urllib import urlencode from aweber_api.response import AWeberResponse from aweber_api.base import API_BASE +import aweber_api + class AWeberCollection(AWeberResponse): """ @@ -57,12 +59,10 @@ def create(self, **kwargs): response = self.adapter.request('POST', self.url, params, response='headers') - if response['status'] != '201': - return False - new_resource = response['location'] - self._diff = {} - self._data = self.adapter.request('GET', new_resource) - return True + + resource_url = response['location'] + data = self.adapter.request('GET', resource_url) + return aweber_api.entry.AWeberEntry(resource_url, data, self.adapter) def find(self, **kwargs): params = {'ws.op': 'find'} diff --git a/aweber_api/entry.py b/aweber_api/entry.py index c9afbd6..02fc288 100644 --- a/aweber_api/entry.py +++ b/aweber_api/entry.py @@ -137,12 +137,12 @@ def get_parent_entry(self): size = len(url_parts) url = self.url[:-len(url_parts[size-1])-1] url = url[:-len(url_parts[size-2])-1] - data = self.adapter.request('GET', url) - try: - entry = AWeberEntry(url, data, self.adapter) - except TypeError: + + if url == '': return None - return entry + + data = self.adapter.request('GET', url) + return AWeberEntry(url, data, self.adapter) def get_web_forms(self): self._method_for('account') diff --git a/aweber_api/oauth.py b/aweber_api/oauth.py index 1590f0f..9ff4454 100644 --- a/aweber_api/oauth.py +++ b/aweber_api/oauth.py @@ -24,29 +24,43 @@ def request(self, method, url, data={}, response='body'): client = self._get_client() url = self._expand_url(url) body = self._prepare_request_body(method, url, data) - try: - # need a test for the next 4 lines below - content_type = 'application/json' - if method == 'GET' and body is not None and body is not '': - # todo: need a better way to do this! - if '?' in url: - url = '{0}&{1}'.format(url, body) - else: - url = '{0}?{1}'.format(url, body) - if method == 'POST': - content_type = 'application/x-www-form-urlencoded' - headers = {'Content-Type' : content_type} - resp, content = client.request(url, method, body=body, - headers=headers) - if response == 'body' and isinstance(content, str): - return self._parse(content) - if response == 'status': - return resp['status'] - if response == 'headers': - return resp - except Exception: - # TODO: refactor this for better error handling - pass + + # need a test for the next 4 lines below + content_type = 'application/json' + if method == 'GET' and body is not None and body is not '': + # todo: need a better way to do this! + if '?' in url: + url = '{0}&{1}'.format(url, body) + else: + url = '{0}?{1}'.format(url, body) + if method == 'POST': + content_type = 'application/x-www-form-urlencoded' + headers = {'Content-Type' : content_type} + + resp, content = client.request(url, method, body=body, + headers=headers) + if int(resp['status']) >= 400: + """ + API Service Errors: + + Please review the Exception that is raised it should indicate + what the error is. + + refer to https://labs.aweber.com/docs/troubleshooting for more + details. + """ + content = json.loads(content) + error = content.get('error', {}) + error_type = error.get('type') + error_msg = error.get('message') + raise Exception('{0}: {1}'.format(error_type, error_msg)) + + if response == 'body' and isinstance(content, str): + return self._parse(content) + if response == 'status': + return resp['status'] + if response == 'headers': + return resp return None def _expand_url(self, url): diff --git a/tests/data/custom_fields/505454.json b/tests/data/custom_fields/505454.json new file mode 100644 index 0000000..37ff0b1 --- /dev/null +++ b/tests/data/custom_fields/505454.json @@ -0,0 +1 @@ +{"total_size": 0, "start": 0, "resource_type_link": "https://api.aweber.com/1.0/#custom_field-page-resource", "entries": []} diff --git a/tests/data/custom_fields/error.json b/tests/data/custom_fields/error.json new file mode 100644 index 0000000..7b0408f --- /dev/null +++ b/tests/data/custom_fields/error.json @@ -0,0 +1 @@ +{"error": {"message": "name: must be unique.", "type": "BadRequestError"}} diff --git a/tests/data/error.json b/tests/data/error.json index bb8eb9b..623bc5f 100644 --- a/tests/data/error.json +++ b/tests/data/error.json @@ -1 +1 @@ -{"error": {"message": "Missing required parameter 'oauth_consumer_key'.", "type": "MissingRequiredOAuthParameterError"}} +{"error": {"message": "Simulated Exception", "type": "BadRequestError"}} diff --git a/tests/data/subscribers/get_activity_ts.json b/tests/data/subscribers/get_activity_ts.json new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/tests/data/subscribers/get_activity_ts.json @@ -0,0 +1 @@ +1 diff --git a/tests/mock_adapter.py b/tests/mock_adapter.py index 340d205..111e1cf 100644 --- a/tests/mock_adapter.py +++ b/tests/mock_adapter.py @@ -26,12 +26,21 @@ '/accounts/1/lists/505454': ({}, 'lists/505454'), '/accounts/1/lists/303449/campaigns': ({}, 'campaigns/303449'), '/accounts/1/lists/303449/custom_fields': ({}, 'custom_fields/303449'), + '/accounts/1/lists/505454/custom_fields': ({}, 'custom_fields/505454'), '/accounts/1/lists/303449/custom_fields/1': ({}, 'custom_fields/1'), '/accounts/1/lists/303449/custom_fields/2': ({}, 'custom_fields/2'), '/accounts/1/lists/303449/subscribers': ({}, 'subscribers/page1'), '/accounts/1/lists/303449/subscribers/1': ({}, 'subscribers/1'), '/accounts/1/lists/303449/subscribers/2': ({}, 'subscribers/2'), '/accounts/1/lists/505454/subscribers/3': ({}, 'subscribers/3'), + '/accounts/1/lists/303449/subscribers/1?ws.op=getActivity': ( + {}, 'subscribers/get_activity'), + '/accounts/1/lists/303449/subscribers/1?ws.op=getActivity&ws.show=total_size': ( + {}, 'subscribers/get_activity_ts'), + '/accounts/1/lists/303449/subscribers?ws.op=find&name=joe': ( + {'status': '400'}, 'error'), + '/accounts/1?ws.op=findSubscribers&name=bob': ( + {'status': '400'}, 'error'), '/accounts/1/lists/303449/subscribers?ws.op=find&' \ 'email=joe%40example.com': ({}, 'subscribers/find'), '/accounts/1/lists/303449/subscribers?ws.op=find&' \ @@ -42,17 +51,19 @@ '/accounts/1/lists/303449/custom_fields': ({ 'status': '201', 'location': '/accounts/1/lists/303449/custom_fields/2'}, None), + '/accounts/1/lists/505454/custom_fields': ({ + 'status': '400'}, 'custom_fields/error'), '/accounts/1/lists/303449/subscribers/1': ({ 'status': '201', 'location': '/accounts/1/lists/505454/subscribers/3'}, None), }, 'PATCH' : { '/accounts/1/lists/303449/subscribers/1': ({}, None), - '/accounts/1/lists/303449/subscribers/2': ({'status': '403'}, None), + '/accounts/1/lists/303449/subscribers/2': ({'status': '400'}, 'error'), }, 'DELETE' : { - '/accounts/1/lists/303449/subscribers/1': ({}, None), - '/accounts/1/lists/303449/subscribers/2': ({'status': '403'}, None), + '/accounts/1/lists/303449/subscribers/1': ({'status': '200'}, None), + '/accounts/1/lists/303449/subscribers/2': ({'status': '400'}, 'error'), } } diff --git a/tests/test_aweber_collection.py b/tests/test_aweber_collection.py index 0beb7a6..b20f5fa 100644 --- a/tests/test_aweber_collection.py +++ b/tests/test_aweber_collection.py @@ -56,13 +56,7 @@ def test_should_support_find_method(self): def test_find_should_handle_errors(self): base_url = '/accounts/1/lists/303449/subscribers' subscriber_collection = self.aweber.load_from_url(base_url) - self.aweber.adapter.requests = [] - subscribers = subscriber_collection.find(name='joe') - request = self.aweber.adapter.requests[0] - - assert subscribers == False - assert request['url'] == \ - '{0}?ws.op=find&name=joe'.format(base_url) + self.assertRaises(Exception, subscriber_collection.find, name='joe') def test_should_create_entries_with_correct_url(self): base_url = '/accounts/1' @@ -72,6 +66,19 @@ def test_should_create_entries_with_correct_url(self): assert subscriber.url == subscriber.self_link.replace(API_BASE, '') +class TestWhenCreatingCustomFieldsFails(TestCase): + + def setUp(self): + self.aweber = AWeberAPI('1', '2') + self.aweber.adapter = MockAdapter() + cf_url = '/accounts/1/lists/505454/custom_fields' + self.cf = self.aweber.load_from_url(cf_url) + self.aweber.adapter.requests = [] + + def test_should_raise_exception(self): + self.assertRaises(Exception, self.cf.create, name='Duplicate Name') + + class TestCreatingCustomFields(TestCase): def setUp(self): @@ -85,8 +92,12 @@ def setUp(self): self.create_req = self.aweber.adapter.requests[0] self.get_req = self.aweber.adapter.requests[1] - def test_returned_true(self): - self.assertTrue(self.resp) + def test_should_return_new_resource_entry_object(self): + assert isinstance(self.resp, AWeberEntry) + assert self.resp.name == u'COLOR' + assert self.resp.is_subscriber_updateable == True + assert self.resp.id == 2 + assert self.resp.url == '/accounts/1/lists/303449/custom_fields/2' def test_should_have_requested_create_with_post(self): self.assertEqual(self.create_req['method'], 'POST') diff --git a/tests/test_aweber_entry.py b/tests/test_aweber_entry.py index 2232e35..1280161 100644 --- a/tests/test_aweber_entry.py +++ b/tests/test_aweber_entry.py @@ -28,15 +28,8 @@ def test_should_have_child_collections(self): self.assertEqual(type(campaigns), AWeberCollection) def test_findSubscribers_should_handle_errors(self): - base_url = '/accounts/1' - account = self.aweber.load_from_url(base_url) - self.aweber.adapter.requests = [] - subscribers = account.findSubscribers(name='bob') - request = self.aweber.adapter.requests[0] - - assert subscribers == False - assert request['url'] == \ - '{0}?ws.op=findSubscribers&name=bob'.format(base_url) + account = self.aweber.load_from_url('/accounts/1') + self.assertRaises(Exception, account.findSubscribers, name='bob') class AccountTestCase(TestCase): @@ -232,11 +225,9 @@ def setUp(self): self.subscriber = self.aweber.load_from_url(sub_url) self.subscriber.name = 'Gary Oldman' self.subscriber.custom_fields['New Custom Field'] = 'Cookies' - self.resp = self.subscriber.save() - self.req = self.aweber.adapter.requests[0] def test_save_failed(self): - self.assertFalse(self.resp) + self.assertRaises(Exception, self.subscriber.save) class TestDeletingSubscriberData(SubscriberTestCase): @@ -264,12 +255,9 @@ def setUp(self): self.aweber.adapter = MockAdapter() sub_url = '/accounts/1/lists/303449/subscribers/2' self.subscriber = self.aweber.load_from_url(sub_url) - self.aweber.adapter.requests = [] - self.response = self.subscriber.delete() - self.req = self.aweber.adapter.requests[0] - def test_should_have_failed(self): - self.assertFalse(self.response) + def test_should_raise_exception_when_failing(self): + self.assertRaises(Exception, self.subscriber.delete) class TestGettingParentEntry(TestCase): @@ -279,6 +267,8 @@ def setUp(self): self.aweber.adapter = MockAdapter() self.list = self.aweber.load_from_url('/accounts/1/lists/303449') self.account = self.aweber.load_from_url('/accounts/1') + #print self.account._data + #1/0 self.custom_field = self.aweber.load_from_url('/accounts/1/lists/303449/custom_fields/1') def test_should_be_able_get_parent_entry(self):