diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..9231629 --- /dev/null +++ b/README.rst @@ -0,0 +1,111 @@ +About +----- + +The AWeber API Python Library allows you to quickly get up and running with +integrating access to the AWeber API into your Python applications. This +egg requires the python-oauth2 to handle the authentication. + +Installation +============ + +This egg can be installed by checking out the source:: + + $ sudo python setup.py install + +Or from Pypi:: + + $ easy_install -U aweber_api + +Usage +===== + +To connect the AWeber API Python Libray, you simply include the main class, +AWeberAPI in your application, then create an instace of it with your +application's consumer key and secret:: + + from aweber import AWeberAPI + aweber = AWeberAPI(consumer_key, consumer_secret) + account = aweber.get_account(access_token, token_secret) + + for list in account.lists: + print list.name + + +Getting request tokens / access tokens +++++++++++++++++++++++++++++++++++++++ + +You can also use the AWeberAPI object to handle retrieving request tokens:: + + from aweber import AWeberAPI + aweber = AWeberAPI(consumer_key, consumer_secret) + request_token, request_token_secret = aweber.get_request_token(callback_url) + print aweber.authorize_url + +As well as access tokens:: + + from aweber import AWeberAPI + aweber = AWeberAPI(consumer_key, consumer_secret) + aweber.user.verifier = verifier + aweber.user.request_token = request_token + aweber.user.token_secret = request_token_secret + access_token, access_token_secret = aweber.get_access_token() + + +Full Pylons example ++++++++++++++++++++ + +Here is a simple Pylons example that uses the AWeber API Python Library to get +a request token, have it authorized, and then print some basic stats about the +web forms in that user's first list:: + + from pylons import session, request, tmpl_context as c + from pylons.controllers.util import redirect + + from awebertest.lib.base import BaseController, render + + from aweber_api import AWeberAPI + + url = 'http://localhost:5000' + consumer_key = "vjckgsr5y4gfOa3PWnf" + consumer_secret = "u3sQ7vGGJBfds4q5dfgsTESi685c5x2wm6gZuIj" + class DemoController(BaseController): + + def __before__(self): + self.aweber = AWeberAPI(consumer_key, consumer_secret) + + def index(self): + token, secret = self.aweber.get_request_token(url+'/demo/get_access') + session['request_token_secret'] = secret + session.save() + redirect(self.aweber.authorize_url) + + def get_access(self): + self.aweber.user.request_token = request.params['oauth_token'] + self.aweber.user.token_secret = session['request_token_secret'] + self.aweber.user.verifier = request.params['oauth_verifier'] + session['token'], session['secret'] = self.aweber.get_access_token() + session.save() + redirect(url+'/demo/show') + + def show(self): + c.account = self.aweber.get_account(session['token'], session['secret']) + return render('data.mako') + + +In `data.mako`:: + + + + +

Web Forms

+ % for list in c.account.lists: + List Id: ${list.id}, name: ${list.name}
+ Currently has: ${len(list.web_forms)} web forms + + % endfor + + diff --git a/aweber_api.egg-info/PKG-INFO b/aweber_api.egg-info/PKG-INFO new file mode 100644 index 0000000..f53dc95 --- /dev/null +++ b/aweber_api.egg-info/PKG-INFO @@ -0,0 +1,10 @@ +Metadata-Version: 1.0 +Name: aweber-api +Version: 1.0.0 +Summary: UNKNOWN +Home-page: UNKNOWN +Author: UNKNOWN +Author-email: UNKNOWN +License: UNKNOWN +Description: UNKNOWN +Platform: UNKNOWN diff --git a/aweber_api.egg-info/SOURCES.txt b/aweber_api.egg-info/SOURCES.txt new file mode 100644 index 0000000..30a7136 --- /dev/null +++ b/aweber_api.egg-info/SOURCES.txt @@ -0,0 +1,11 @@ +setup.py +aweber_api/__init__.py +aweber_api/base.py +aweber_api/collection.py +aweber_api/entry.py +aweber_api/oauth.py +aweber_api/response.py +aweber_api.egg-info/PKG-INFO +aweber_api.egg-info/SOURCES.txt +aweber_api.egg-info/dependency_links.txt +aweber_api.egg-info/top_level.txt \ No newline at end of file diff --git a/aweber_api.egg-info/dependency_links.txt b/aweber_api.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/aweber_api.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/aweber_api.egg-info/top_level.txt b/aweber_api.egg-info/top_level.txt new file mode 100644 index 0000000..5ca1f7a --- /dev/null +++ b/aweber_api.egg-info/top_level.txt @@ -0,0 +1 @@ +aweber_api diff --git a/aweber_api/.base.py.swp b/aweber_api/.base.py.swp new file mode 100644 index 0000000..7080f19 Binary files /dev/null and b/aweber_api/.base.py.swp differ diff --git a/aweber_api/.collection.py.swp b/aweber_api/.collection.py.swp new file mode 100644 index 0000000..e6edd1a Binary files /dev/null and b/aweber_api/.collection.py.swp differ diff --git a/aweber_api/.entry.py.swp b/aweber_api/.entry.py.swp new file mode 100644 index 0000000..f4cdc55 Binary files /dev/null and b/aweber_api/.entry.py.swp differ diff --git a/aweber_api/.oauth.py.swp b/aweber_api/.oauth.py.swp new file mode 100644 index 0000000..61684b5 Binary files /dev/null and b/aweber_api/.oauth.py.swp differ diff --git a/aweber_api/.response.py.swp b/aweber_api/.response.py.swp new file mode 100644 index 0000000..8a6e0ad Binary files /dev/null and b/aweber_api/.response.py.swp differ diff --git a/aweber_api/__init__.py b/aweber_api/__init__.py new file mode 100644 index 0000000..3d0717f --- /dev/null +++ b/aweber_api/__init__.py @@ -0,0 +1,99 @@ +from urlparse import parse_qs + +from aweber_api.base import (AWeberBase, API_BASE, ACCESS_TOKEN_URL, + REQUEST_TOKEN_URL, AUTHORIZE_URL) +from aweber_api.collection import AWeberCollection +from aweber_api.entry import AWeberEntry +from aweber_api.oauth import OAuthAdapter +from aweber_api.response import AWeberResponse + +class AWeberAPI(AWeberBase): + """ Base class for connecting to the AWeberAPI. Created with a consumer key + and secret, then used to either generate tokens for authorizing a user, or + can be provided tokens and used to access that user's resources. """ + + def __init__(self, consumer_key, consumer_secret): + self.adapter = OAuthAdapter(consumer_key, consumer_secret, API_BASE) + self.adapter.user = AWeberUser() + + @property + def authorize_url(self): + """ + Returns the authorize url, potentially containing the request token + parameter + """ + if self.user.request_token: + return "{0}?oauth_token={1}".format(AUTHORIZE_URL, + self.user.request_token) + return AUTHORIZE_URL + + def get_request_token(self, callback_url): + """ + Gets a new request token / token secret for the given callback URL + and the current consumer. Returns token / secret, and sets properties + on the AWeberUser object (self.user) + """ + data = { 'oauth_callback' : callback_url } + response = self.adapter.request('POST', + REQUEST_TOKEN_URL, + data) + self.user.request_token, self.user.token_secret = self.\ + _parse_token_response(response) + return (self.user.request_token, self.user.token_secret) + + def get_access_token(self): + """ + Gets an access token for the given request token / token secret / + verifier combination in the AWeberUser object at self.user + Updates the user object and returns the tokens + """ + + data = { 'oauth_verifier' : self.user.verifier } + response = self.adapter.request('POST', + ACCESS_TOKEN_URL, + data) + self.user.access_token, self.user.token_secret = self.\ + _parse_token_response(response) + return (self.user.access_token, self.user.token_secret) + + def _parse_token_response(self, response): + if not type(response) == str: + raise TypeError('Expected response to be a string') + + data = parse_qs(response) + + if not 'oauth_token' in data and not 'oauth_token_secret' in data: + raise ValueError('OAuth parameters not returned') + return (data['oauth_token'][0], data['oauth_token_secret'][0]) + + def get_account(self, access_token=False, token_secret=False): + """ + Returns the AWeberEntry object for the account specified by the + access_token and token_secret currently in the self.user object. + Optionally, access_token and token_secret can be provided to replace + the properties in self.user.access_token and self.user.token_secret, + respectively. + """ + if access_token: + self.user.access_token = access_token + if token_secret: + self.user.token_secret = token_secret + url = '/accounts' + response = self.adapter.request('GET', url) + accounts = self._read_response(url, response) + return accounts[0] + +class AWeberUser(object): + """ + Simple data storage object representing the user in the OAuth model. Has + properties for request_token, token_secret, access_token, and verifier. + """ + + request_token = None + token_secret = None + access_token = None + verifier = None + + def get_highest_priority_token(self): + return self.access_token or self.request_token + diff --git a/aweber_api/__init__.pyc b/aweber_api/__init__.pyc new file mode 100644 index 0000000..3c9acc4 Binary files /dev/null and b/aweber_api/__init__.pyc differ diff --git a/aweber_api/base.py b/aweber_api/base.py new file mode 100644 index 0000000..8f9dafc --- /dev/null +++ b/aweber_api/base.py @@ -0,0 +1,54 @@ +API_BASE = 'https://api.aweber.com/1.0' +ACCESS_TOKEN_URL = 'https://auth.aweber.com/1.0/oauth/access_token' +REQUEST_TOKEN_URL = 'https://auth.aweber.com/1.0/oauth/request_token' +AUTHORIZE_URL = 'https://auth.aweber.com/1.0/oauth/authorize' + +class AWeberBase(object): + """ + Provides functionality shared accross all AWeber objects + """ + + collections_map = { + 'account' : ['lists', 'vendor_accounts'], + 'broadcast_campaign' : ['links', 'messages'], + 'followup_campaign' : ['links', 'messages'], + 'link' : ['clicks'], + 'list' : ['campaigns', 'subscribers', 'web_forms', + 'web_form_split_tests'], + 'message' : ['opens', 'tracked_events'], + 'subscriber' : [], + 'web_form': [], + 'web_form_split_test' : ['components'] + } + + @property + def user(self): + return self.adapter.user + + def load_from_url(self, url): + """ + Gets an AWeberCollection or AWeberEntry from the given URL. + """ + response = self.adapter.request('GET', url) + return self._read_response(url, response) + + def _method_for(self, type): + if not self.type == type: + raise AttributeError('Method does not exist') + + def _read_response(self, url, response): + if 'entries' in response: + from aweber_api.collection import AWeberCollection + return AWeberCollection(url, response, self.adapter) + if 'id' in response: + from aweber_api.entry import AWeberEntry + return AWeberEntry(url, response, self.adapter) + raise TypeError('Unknown value returned') + + def _parseNamedOperation(self, data): + from aweber_api.entry import AWeberEntry + entries = [] + for item in data: + entries.append(AWeberEntry(item['self_link'].replace(API_BASE, ''), + item, self.adapter)) + return entries diff --git a/aweber_api/base.pyc b/aweber_api/base.pyc new file mode 100644 index 0000000..56fbc9a Binary files /dev/null and b/aweber_api/base.pyc differ diff --git a/aweber_api/collection.py b/aweber_api/collection.py new file mode 100644 index 0000000..a22bc25 --- /dev/null +++ b/aweber_api/collection.py @@ -0,0 +1,81 @@ +from math import floor +from urlparse import parse_qs +from aweber_api.response import AWeberResponse + +class AWeberCollection(AWeberResponse): + """ + Represents a collection of similar objects. Encapsulates data that is + found at the base URI's for a given object type, ie: + /accounts + /accounts/XXX/lists + Parses the data from the response and provides basic sequence like + operations, such as iteration and indexing to access the entries that + are contained in this collection. + """ + page_size = 100 + + def __init__(self, url, data, adapter): + self._entry_data = {} + self._current = 0 + + AWeberResponse.__init__(self, url, data, adapter) + self._key_entries(self._data) + + def get_by_id(self, id): + """ + Returns an entry from this collection, as found by its actual + AWeber id, not its offset. Will actually request the data from + the API. + """ + return self.load_from_url("{0}/{1}".format(self.url, id)) + + def _key_entries(self, response): + count = 0 + for entry in response['entries']: + self._entry_data[count+response['start']] = entry + count += 1 + + def _load_page_for_offset(self, offset): + page = self._get_page_params(offset) + response = self.adapter.request('GET', self.url, page) + self._key_entries(response) + + def _get_page_params(self, offset): + next_link = self._data['next_collection_link'] + url, query = next_link.split('?') + query_parts = parse_qs(query) + self.page_size = int(query_parts['ws.size'][0]) + page_number = int(floor(offset / self.page_size)) + start = page_number * self.page_size + return { 'ws.start' : start, 'ws.size' : self.page_size } + + def _create_entry(self, offset): + from aweber_api.entry import AWeberEntry + data = self._entry_data[offset] + + url = "{0}/{1}".format(self.url, data['id']) + self._entries[offset] = AWeberEntry(url, data, self.adapter) + + def __len__(self): + return self.total_size + + def __iter__(self): + return self + + def next(self): + if self._current < self.total_size: + self._current += 1 + return self[self._current-1] + self._current = 0 + raise StopIteration + + def __getitem__(self, offset): + if offset < 0 or offset >= self._data['total_size']: + raise ValueError('Offset {0} does not exist'.format(offset)) + + if not offset in self._entries: + if not offset in self._entry_data: + self._load_page_for_offset(offset) + self._create_entry(offset) + return self._entries[offset] + diff --git a/aweber_api/collection.pyc b/aweber_api/collection.pyc new file mode 100644 index 0000000..70d02e5 Binary files /dev/null and b/aweber_api/collection.pyc differ diff --git a/aweber_api/entry.py b/aweber_api/entry.py new file mode 100644 index 0000000..a348716 --- /dev/null +++ b/aweber_api/entry.py @@ -0,0 +1,42 @@ +from aweber_api.response import AWeberResponse + +class AWeberEntry(AWeberResponse): + """ + Represents a single entry in the AWeber API data heirarchy, such as one + specific account, list, web form, etc. Built on data that is returned + from an id-ed URI, such as: + /accounts/XXXX + /accounts/XXXX/lists/XXXX + Can also be generated from the data in the entries array of a collection + object, which is identical to the data return from the URI for that + specific entry. + + Provides direct access to properties in the response, such as self.id + """ + + def __init__(self, url, data, adapter): + AWeberResponse.__init__(self, url, data, adapter) + self._child_collections = {} + + + def get_web_forms(self): + self._method_for('account') + data = self.adapter.request('GET', + "{0}?ws.op=getWebForms".format(self.url)) + return self._parseNamedOperation(data) + + def _child_collection(self, attr): + if not attr in self._child_collections: + url = "{0}/{1}".format(self.url, attr) + self._child_collections[attr] = self.load_from_url(url) + return self._child_collections[attr] + + def __getattr__(self, attr): + if attr in self._data: + return self._data[attr] + elif attr in self.collections_map[self.type]: + return self._child_collection(attr) + else: + raise AttributeError(attr) + + diff --git a/aweber_api/entry.pyc b/aweber_api/entry.pyc new file mode 100644 index 0000000..10c6e32 Binary files /dev/null and b/aweber_api/entry.pyc differ diff --git a/aweber_api/oauth.py b/aweber_api/oauth.py new file mode 100644 index 0000000..8524648 --- /dev/null +++ b/aweber_api/oauth.py @@ -0,0 +1,45 @@ +import oauth2 as oauth +import json + +class OAuthAdapter(object): + + def __init__(self, key, secret, base): + self.key = key + self.secret = secret + self.consumer = oauth.Consumer(key=self.key, secret=self.secret) + self.api_base = base + + def _parse(self, response): + try: + data = json.loads(response) + if not data or data == '': + return response + return data + except: + pass + return response + + def request(self, method, url, data={}): + token = self.user.get_highest_priority_token() + if token: + token = oauth.Token(token, self.user.token_secret) + client = oauth.Client(self.consumer, token=token) + else: + client = oauth.Client(self.consumer) + + if not url[:4] == 'http': + url = '%s%s' % (self.api_base, url) + + if len(data.keys()) == 0: + body = None + else: + body = '&'.join(map(lambda x: "{0}={1}".format(x, data[x]), + data.keys())) + + try: + resp, content = client.request(url, method, body=body) + if type(content) == str: + return self._parse(content) + except e: + pass + return None diff --git a/aweber_api/oauth.pyc b/aweber_api/oauth.pyc new file mode 100644 index 0000000..2bc30ff Binary files /dev/null and b/aweber_api/oauth.pyc differ diff --git a/aweber_api/response.py b/aweber_api/response.py new file mode 100644 index 0000000..fcc6121 --- /dev/null +++ b/aweber_api/response.py @@ -0,0 +1,29 @@ +from aweber_api import AWeberBase + +class AWeberResponse(AWeberBase): + + def __init__(self, url, data, adapter): + self._type = None + self.adapter = adapter + self.url = url + self._data = data + self._entries = {} + + def _generate_type(self): + if 'resource_type_link' in self._data: + type = self._data['resource_type_link'] + self._type = type.split('#').pop() + return None + + @property + def type(self): + if not self._type: + self._generate_type() + return self._type + + def __getattr__(self, attr): + if attr in self._data: + return self._data[attr] + else: + raise AttributeError(attr) + diff --git a/aweber_api/response.pyc b/aweber_api/response.pyc new file mode 100644 index 0000000..3231da3 Binary files /dev/null and b/aweber_api/response.pyc differ diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..a816493 --- /dev/null +++ b/setup.py @@ -0,0 +1,10 @@ +from setuptools import setup, find_packages + +setup( + name='aweber_api', + version='1.0.0', + packages=find_packages(exclude=['tests']), + test_suite='nose.collector', + include_package_data=True +) + diff --git a/tests/data/account.json b/tests/data/account.json new file mode 100644 index 0000000..4782e1e --- /dev/null +++ b/tests/data/account.json @@ -0,0 +1 @@ +{"http_etag": "\"5ae3075ce7c9b1869ce83bf2a7d67da376af0031-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "lists_collection_link": "https://api.aweber.com/1.0/accounts/326084/lists", "self_link": "https://api.aweber.com/1.0/accounts/326084", "resource_type_link": "https://api.aweber.com/1.0/#account", "id": 326084, "integrations_collection_link": "https://api.aweber.com/1.0/accounts/326084/integrations"} diff --git a/tests/data/accounts.json b/tests/data/accounts.json new file mode 100644 index 0000000..0e0edc4 --- /dev/null +++ b/tests/data/accounts.json @@ -0,0 +1,9 @@ +{"total_size": 1, "start": 0, "next_collection_link": +"http://api.apitest.lab:81/0.1/accounts?ws.start=20&ws.size=20", "entries": +[{"http_etag": +"\"c70dfb07dc67c9dd6a8bc01130acf68d1fbf035f-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", +"vendor_accounts_collection_link": +"http://api.apitest.lab:81/0.1/accounts/910/vendor_accounts", +"lists_collection_link": "http://api.apitest.lab:81/0.1/accounts/910/lists", +"self_link": "http://api.apitest.lab:81/0.1/accounts/910", +"resource_type_link": "http://api.apitest.lab:81/0.1/#account", "id": 910}], "resource_type_link" : "http://api.apitest.lab:81/0.1/#accounts"} diff --git a/tests/data/error.json b/tests/data/error.json new file mode 100644 index 0000000..bb8eb9b --- /dev/null +++ b/tests/data/error.json @@ -0,0 +1 @@ +{"error": {"message": "Missing required parameter 'oauth_consumer_key'.", "type": "MissingRequiredOAuthParameterError"}} diff --git a/tests/data/lists.json b/tests/data/lists.json new file mode 100644 index 0000000..fc113ef --- /dev/null +++ b/tests/data/lists.json @@ -0,0 +1 @@ +{"total_size": 24, "start": 0, "next_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists?ws.start=20&ws.size=20", "entries": [{"campaigns_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/251847/campaigns", "name": "default251847", "subscribers_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/251847/subscribers", "id": 251847, "http_etag": "\"dac7041022b8d1b9690fbc0a34121a19c0461781-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/251847", "resource_type_link": "http://api.apitest.lab:81/0.1/#list", "web_forms_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/251847/web_forms"}, {"campaigns_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/251846/campaigns", "name": "default251846", "subscribers_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/251846/subscribers", "id": 251846, "http_etag": "\"acefbf9202cfd5d156006591fa0222b7e4f735d2-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/251846", "resource_type_link": "http://api.apitest.lab:81/0.1/#list", "web_forms_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/251846/web_forms"}, {"campaigns_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/251845/campaigns", "name": "default251845", "subscribers_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/251845/subscribers", "id": 251845, "http_etag": "\"a2845b27890ae073977798afe229933c00b6604a-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/251845", "resource_type_link": "http://api.apitest.lab:81/0.1/#list", "web_forms_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/251845/web_forms"}, {"campaigns_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/251843/campaigns", "name": "default251843", "subscribers_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/251843/subscribers", "id": 251843, "http_etag": "\"80ef114161f2e417ce3da2a5ae0f45e1f9e2a17d-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/251843", "resource_type_link": "http://api.apitest.lab:81/0.1/#list", "web_forms_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/251843/web_forms"}, {"campaigns_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/312802/campaigns", "name": "anewtestlist", "subscribers_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/312802/subscribers", "id": 312802, "http_etag": "\"b4408834c0f13761cc2f4b90784e1faee5b8d084-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/312802", "resource_type_link": "http://api.apitest.lab:81/0.1/#list", "web_forms_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/312802/web_forms"}, {"campaigns_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/251848/campaigns", "name": "testmc", "subscribers_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/251848/subscribers", "id": 251848, "http_etag": "\"be0d61f3d6cbf34819f74e994b1ffa2c96ed7bb3-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/251848", "resource_type_link": "http://api.apitest.lab:81/0.1/#list", "web_forms_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/251848/web_forms"}, {"campaigns_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/303449/campaigns", "name": "default303449", "subscribers_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/303449/subscribers", "id": 303449, "http_etag": "\"5ba07c4b65dd1f6d245a7fd0dada5ea65b0f054d-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/303449", "resource_type_link": "http://api.apitest.lab:81/0.1/#list", "web_forms_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/303449/web_forms"}, {"campaigns_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/305162/campaigns", "name": "herewego12", "subscribers_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/305162/subscribers", "id": 305162, "http_etag": "\"03a0ec4e9f52a0a1a99a8d4a83ef6587eed9a6b8-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/305162", "resource_type_link": "http://api.apitest.lab:81/0.1/#list", "web_forms_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/305162/web_forms"}, {"campaigns_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/226186/campaigns", "name": "test-list777", "subscribers_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/226186/subscribers", "id": 226186, "http_etag": "\"e51bc0351083caca2a811a97937225605e80113c-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/226186", "resource_type_link": "http://api.apitest.lab:81/0.1/#list", "web_forms_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/226186/web_forms"}, {"campaigns_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/251844/campaigns", "name": "default251844", "subscribers_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/251844/subscribers", "id": 251844, "http_etag": "\"fd2ed44b31f0b07b1c3e1d8cc094c152e83b2dc5-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/251844", "resource_type_link": "http://api.apitest.lab:81/0.1/#list", "web_forms_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/251844/web_forms"}, {"campaigns_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/1/campaigns", "name": "test-list2fff", "subscribers_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/1/subscribers", "id": 1, "http_etag": "\"a2e27930058f806c597e52b9f069284cff575588-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/1", "resource_type_link": "http://api.apitest.lab:81/0.1/#list", "web_forms_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/1/web_forms"}, {"campaigns_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/301413/campaigns", "name": "test-list1d", "subscribers_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/301413/subscribers", "id": 301413, "http_etag": "\"6a4f25e78b120a99951beae31f3d9491f19d6719-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/301413", "resource_type_link": "http://api.apitest.lab:81/0.1/#list", "web_forms_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/301413/web_forms"}, {"campaigns_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/320972/campaigns", "name": "superbenk", "subscribers_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/320972/subscribers", "id": 320972, "http_etag": "\"cd895b82944e86aefd492949d8b7d923d7d28778-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/320972", "resource_type_link": "http://api.apitest.lab:81/0.1/#list", "web_forms_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/320972/web_forms"}, {"campaigns_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/363010/campaigns", "name": "default363010", "subscribers_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/363010/subscribers", "id": 363010, "http_etag": "\"4b095ec0243d40ab613096d8d3f96a609fdd27d5-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/363010", "resource_type_link": "http://api.apitest.lab:81/0.1/#list", "web_forms_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/363010/web_forms"}, {"campaigns_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/307014/campaigns", "name": "devteamtest_2", "subscribers_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/307014/subscribers", "id": 307014, "http_etag": "\"d78abf7131f250f0929a6558f000b8760e76155b-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/307014", "resource_type_link": "http://api.apitest.lab:81/0.1/#list", "web_forms_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/307014/web_forms"}, {"campaigns_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/305164/campaigns", "name": "homer_simpson", "subscribers_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/305164/subscribers", "id": 305164, "http_etag": "\"568306713e4d297e2f40948e63f240b1798fc3d8-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/305164", "resource_type_link": "http://api.apitest.lab:81/0.1/#list", "web_forms_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/305164/web_forms"}, {"campaigns_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/363013/campaigns", "name": "default363013", "subscribers_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/363013/subscribers", "id": 363013, "http_etag": "\"4eee1ea48164b794be3891422d0ddbede8c26ecc-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/363013", "resource_type_link": "http://api.apitest.lab:81/0.1/#list", "web_forms_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/363013/web_forms"}, {"campaigns_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/363014/campaigns", "name": "default363014", "subscribers_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/363014/subscribers", "id": 363014, "http_etag": "\"511a9e0afca20511da481093d1742ce1d3a791bf-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/363014", "resource_type_link": "http://api.apitest.lab:81/0.1/#list", "web_forms_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/363014/web_forms"}, {"campaigns_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/363009/campaigns", "name": "super", "subscribers_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/363009/subscribers", "id": 363009, "http_etag": "\"570519a927e3bf6a13499bff4c10339ed8572216-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/363009", "resource_type_link": "http://api.apitest.lab:81/0.1/#list", "web_forms_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/363009/web_forms"}, {"campaigns_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/50000003/campaigns", "name": "default50000003", "subscribers_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/50000003/subscribers", "id": 50000003, "http_etag": "\"0f1b51f3c1fa3f61fe29a7783312371cc4f42149-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/50000003", "resource_type_link": "http://api.apitest.lab:81/0.1/#list", "web_forms_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/50000003/web_forms"}], "resource_type_link" : "http://api.apitest.lab:81/0.1/#list-page-resource"} diff --git a/tests/data/lists/303449.json b/tests/data/lists/303449.json new file mode 100644 index 0000000..582192b --- /dev/null +++ b/tests/data/lists/303449.json @@ -0,0 +1 @@ +{"campaigns_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/303449/campaigns", "name": "default303449", "subscribers_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/303449/subscribers", "id": 303449, "http_etag": "\"5ba07c4b65dd1f6d245a7fd0dada5ea65b0f054d-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/303449", "resource_type_link": "http://api.apitest.lab:81/0.1/#list", "web_forms_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/303449/web_forms"} diff --git a/tests/data/lists/303449/campaigns.json b/tests/data/lists/303449/campaigns.json new file mode 100644 index 0000000..1ff9a96 --- /dev/null +++ b/tests/data/lists/303449/campaigns.json @@ -0,0 +1 @@ +{"total_size": 0, "start": null, "entries": [], "resource_type_link" : "http://api.apitest.lab:81/0.1/#campaign-page-resource"} diff --git a/tests/data/lists_page2.json b/tests/data/lists_page2.json new file mode 100644 index 0000000..2bf6446 --- /dev/null +++ b/tests/data/lists_page2.json @@ -0,0 +1 @@ +{"total_size": 24, "start": 20, "prev_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists?ws.start=0&ws.size=20", "entries": [{"campaigns_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/50000002/campaigns", "name": "one_two_test", "subscribers_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/50000002/subscribers", "id": 50000002, "http_etag": "\"daeb57124532aac221374522cb6c07754e71ba21-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/50000002", "resource_type_link": "http://api.apitest.lab:81/0.1/#list", "web_forms_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/50000002/web_forms"}, {"campaigns_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/406860/campaigns", "name": "devteamtest", "subscribers_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/406860/subscribers", "id": 406860, "http_etag": "\"db00e81c0187d524ac56a254636664e14e90184b-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/406860", "resource_type_link": "http://api.apitest.lab:81/0.1/#list", "web_forms_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/406860/web_forms"}, {"campaigns_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/50000054/campaigns", "name": "furedesign_test", "subscribers_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/50000054/subscribers", "id": 50000054, "http_etag": "\"d082409a783f7f4f955cca186e17eb39d4b28045-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/50000054", "resource_type_link": "http://api.apitest.lab:81/0.1/#list", "web_forms_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/50000054/web_forms"}, {"campaigns_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/327293/campaigns", "name": "anewtestlist1", "subscribers_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/327293/subscribers", "id": 327293, "http_etag": "\"99057bd859740bc8cb946dac3bf6d44a3bcc5a72-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "self_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/327293", "resource_type_link": "http://api.apitest.lab:81/0.1/#list", "web_forms_collection_link": "http://api.apitest.lab:81/0.1/accounts/1/lists/327293/web_forms"}], "resource_type_link" : "http://api.apitest.lab:81/0.1/#list-page-resource"} diff --git a/tests/data/web_forms.json b/tests/data/web_forms.json new file mode 100644 index 0000000..24635f0 --- /dev/null +++ b/tests/data/web_forms.json @@ -0,0 +1 @@ +[{"conversion_percentage": 0.0, "unique_conversion_percentage": 0.0, "name": "My Web Form", "total_unique_displays": 0, "type": "styled", "is_active": true, "total_submissions": 0, "self_link": "https://api.aweber.com/1.0/accounts/1/lists/1192556/web_forms/1733464505", "http_etag": "\"81c5932ffaf2418e6547f3db29ff430f83c9ad79-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "total_displays": 0, "resource_type_link": "https://api.aweber.com/1.0/#web_form", "id": 1733464505}, {"conversion_percentage": 33.333333333333329, "unique_conversion_percentage": 100.0, "name": "My Web Form", "total_unique_displays": 1, "type": "styled", "is_active": true, "total_submissions": 1, "self_link": "https://api.aweber.com/1.0/accounts/1/lists/1121402/web_forms/1369283626", "http_etag": "\"29ac5759b22c6d92eec850b40f2e270e42b8f6fd-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "total_displays": 3, "resource_type_link": "https://api.aweber.com/1.0/#web_form", "id": 1369283626}, {"conversion_percentage": 0.11641443538998836, "unique_conversion_percentage": 0.26515151515151519, "name": "Home page, sidebar", "total_unique_displays": 2640, "type": "styled", "is_active": true, "total_submissions": 7, "self_link": "https://api.aweber.com/1.0/accounts/1/lists/1093432/web_forms/356827526", "http_etag": "\"d131de42f8375408f277ccee852edec27fbf8321-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "total_displays": 6013, "resource_type_link": "https://api.aweber.com/1.0/#web_form", "id": 356827526}, {"conversion_percentage": 0.0, "unique_conversion_percentage": 0.0, "name": null, "total_unique_displays": 0, "type": "styled", "is_active": true, "total_submissions": 0, "self_link": "https://api.aweber.com/1.0/accounts/1/lists/771601/web_forms/131500557", "http_etag": "\"1288c4078b1f5a78197f267b9b0e3079320aa015-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "total_displays": 0, "resource_type_link": "https://api.aweber.com/1.0/#web_form", "id": 131500557}, {"conversion_percentage": 0.0, "unique_conversion_percentage": 0.0, "name": "Testing", "total_unique_displays": 0, "type": "inline", "is_active": true, "total_submissions": 0, "self_link": "https://api.aweber.com/1.0/accounts/1/lists/771601/web_forms/180597630", "http_etag": "\"9e0dc548e60eecde94661e53f06380f411118e70-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "total_displays": 0, "resource_type_link": "https://api.aweber.com/1.0/#web_form", "id": 180597630}, {"conversion_percentage": 33.333333333333329, "unique_conversion_percentage": 50.0, "name": "fdsdfsdfdfs", "total_unique_displays": 2, "type": "styled", "is_active": true, "total_submissions": 1, "self_link": "https://api.aweber.com/1.0/accounts/1/lists/771601/web_forms/270024008", "http_etag": "\"50d20937bcc6ae716543f3da492d71302f7ba5da-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "total_displays": 3, "resource_type_link": "https://api.aweber.com/1.0/#web_form", "id": 270024008}, {"conversion_percentage": 0.0, "unique_conversion_percentage": 0.0, "name": "My Web Form", "total_unique_displays": 0, "type": "styled", "is_active": true, "total_submissions": 0, "self_link": "https://api.aweber.com/1.0/accounts/1/lists/771601/web_forms/721555577", "http_etag": "\"82b4eb089fd0b6a0b157bda1373115d146feb59b-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "total_displays": 0, "resource_type_link": "https://api.aweber.com/1.0/#web_form", "id": 721555577}, {"conversion_percentage": 0.0, "unique_conversion_percentage": 0.0, "name": null, "total_unique_displays": 0, "type": "styled", "is_active": true, "total_submissions": 0, "self_link": "https://api.aweber.com/1.0/accounts/1/lists/771601/web_forms/1070664099", "http_etag": "\"76e920f4b1d7ee7763b1f41a59a243a8187aba99-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "total_displays": 0, "resource_type_link": "https://api.aweber.com/1.0/#web_form", "id": 1070664099}, {"conversion_percentage": 0.0, "unique_conversion_percentage": 0.0, "name": null, "total_unique_displays": 0, "type": "styled", "is_active": true, "total_submissions": 1, "self_link": "https://api.aweber.com/1.0/accounts/1/lists/771601/web_forms/2013603311", "http_etag": "\"b6691478c2334176f9c0a0065e729e5511258aa5-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "total_displays": 0, "resource_type_link": "https://api.aweber.com/1.0/#web_form", "id": 2013603311}, {"conversion_percentage": 1.1469142545057347, "unique_conversion_percentage": 3.9585296889726673, "name": "website", "total_unique_displays": 1061, "type": "inline", "is_active": true, "total_submissions": 42, "self_link": "https://api.aweber.com/1.0/accounts/1/lists/771601/web_forms/1077762960", "http_etag": "\"4037f3d1f0c29bb19a3a5d92d13e7f0d96dd3bb1-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "total_displays": 3662, "resource_type_link": "https://api.aweber.com/1.0/#web_form", "id": 1077762960}, {"conversion_percentage": 0.0, "unique_conversion_percentage": 0.0, "name": "blarhg", "total_unique_displays": 1, "type": "inline", "is_active": true, "total_submissions": 0, "self_link": "https://api.aweber.com/1.0/accounts/1/lists/798061/web_forms/668327018", "http_etag": "\"36e02decd31624698c6753a7f6f8b246017ca6f2-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "total_displays": 5, "resource_type_link": "https://api.aweber.com/1.0/#web_form", "id": 668327018}, {"conversion_percentage": 0.0, "unique_conversion_percentage": 0.0, "name": "New Form 785164876", "total_unique_displays": 0, "type": "styled", "is_active": true, "total_submissions": 0, "self_link": "https://api.aweber.com/1.0/accounts/1/lists/798061/web_forms/785164876", "http_etag": "\"99ad3b309fd7caa39cdc74a57093199166847ddb-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "total_displays": 0, "resource_type_link": "https://api.aweber.com/1.0/#web_form", "id": 785164876}, {"conversion_percentage": 0.0, "unique_conversion_percentage": 0.0, "name": "barf", "total_unique_displays": 1, "type": "popover", "is_active": true, "total_submissions": 0, "self_link": "https://api.aweber.com/1.0/accounts/1/lists/798061/web_forms/1437187399", "http_etag": "\"83222600a0690071080e876fdf0d62c948ae0807-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "total_displays": 1, "resource_type_link": "https://api.aweber.com/1.0/#web_form", "id": 1437187399}, {"conversion_percentage": 0.0, "unique_conversion_percentage": 0.0, "name": "Old ass legacy stinky form", "total_unique_displays": 0, "type": "lightbox", "is_active": true, "total_submissions": 0, "self_link": "https://api.aweber.com/1.0/accounts/1/lists/853318/web_forms/1126276203", "http_etag": "\"c8b7aad2c71683c23296ca4469e125fa3af67fee-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "total_displays": 0, "resource_type_link": "https://api.aweber.com/1.0/#web_form", "id": 1126276203}, {"conversion_percentage": 0.0, "unique_conversion_percentage": 0.0, "name": "My Web Form 2", "total_unique_displays": 0, "type": "styled", "is_active": true, "total_submissions": 0, "self_link": "https://api.aweber.com/1.0/accounts/1/lists/853318/web_forms/1222053368", "http_etag": "\"4372b1ea1703db57e6f588d777244c903815c10b-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "total_displays": 0, "resource_type_link": "https://api.aweber.com/1.0/#web_form", "id": 1222053368}, {"conversion_percentage": 400.0, "unique_conversion_percentage": 400.0, "name": "Sample", "total_unique_displays": 1, "type": "styled", "is_active": true, "total_submissions": 4, "self_link": "https://api.aweber.com/1.0/accounts/1/lists/853318/web_forms/1653200290", "http_etag": "\"552639ecbb958d98848a020ab38abce5f805db00-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "total_displays": 1, "resource_type_link": "https://api.aweber.com/1.0/#web_form", "id": 1653200290}, {"conversion_percentage": 0.0, "unique_conversion_percentage": 0.0, "name": "New Form 1900114264", "total_unique_displays": 0, "type": "styled", "is_active": true, "total_submissions": 0, "self_link": "https://api.aweber.com/1.0/accounts/1/lists/853318/web_forms/1900114264", "http_etag": "\"ccb02527c3b7060d649ff8b611ccd4531d46cc85-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "total_displays": 0, "resource_type_link": "https://api.aweber.com/1.0/#web_form", "id": 1900114264}, {"conversion_percentage": 0.0, "unique_conversion_percentage": 0.0, "name": "Form popup", "total_unique_displays": 0, "type": "inline", "is_active": true, "total_submissions": 0, "self_link": "https://api.aweber.com/1.0/accounts/1/lists/853318/web_forms/1938455405", "http_etag": "\"29e56cc073fdf5e9d5dcdcbef5ef9f4adcd0b98e-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "total_displays": 0, "resource_type_link": "https://api.aweber.com/1.0/#web_form", "id": 1938455405}, {"conversion_percentage": 0.0, "unique_conversion_percentage": 0.0, "name": "My Web Form", "total_unique_displays": 0, "type": "styled", "is_active": true, "total_submissions": 0, "self_link": "https://api.aweber.com/1.0/accounts/1/lists/853318/web_forms/2082623301", "http_etag": "\"3023b1ad6b3e0fbc52129deb5a55ce1effd56bef-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "total_displays": 0, "resource_type_link": "https://api.aweber.com/1.0/#web_form", "id": 2082623301}, {"conversion_percentage": 0.0, "unique_conversion_percentage": 0.0, "name": "Sign up for free newsletter", "total_unique_displays": 1, "type": "inline", "is_active": true, "total_submissions": 0, "self_link": "https://api.aweber.com/1.0/accounts/1/lists/853404/web_forms/1276584893", "http_etag": "\"a8ab161350d7e0d244913ff848f301c7ba66029e-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "total_displays": 1, "resource_type_link": "https://api.aweber.com/1.0/#web_form", "id": 1276584893}, {"conversion_percentage": 0.0, "unique_conversion_percentage": 0.0, "name": "New styled form", "total_unique_displays": 1, "type": "styled", "is_active": true, "total_submissions": 0, "self_link": "https://api.aweber.com/1.0/accounts/1/lists/853399/web_forms/992299989", "http_etag": "\"669b36b1c356151329743774bff0edd1bd5a2877-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "total_displays": 3, "resource_type_link": "https://api.aweber.com/1.0/#web_form", "id": 992299989}, {"conversion_percentage": 0.0, "unique_conversion_percentage": 0.0, "name": "Existing Styled form", "total_unique_displays": 0, "type": "styled", "is_active": true, "total_submissions": 0, "self_link": "https://api.aweber.com/1.0/accounts/1/lists/853399/web_forms/1716841568", "http_etag": "\"013c2ffd669a6dff74db540bcaaaebc2494ef682-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "total_displays": 0, "resource_type_link": "https://api.aweber.com/1.0/#web_form", "id": 1716841568}, {"conversion_percentage": 0.0, "unique_conversion_percentage": 0.0, "name": "Legacy form", "total_unique_displays": 0, "type": "styled", "is_active": true, "total_submissions": 0, "self_link": "https://api.aweber.com/1.0/accounts/1/lists/853399/web_forms/2120561755", "http_etag": "\"c58a76526d5614ae99fac801207b18851b8f6284-ca5feee2b7fbb6febfca8af5541541ea960aaedb\"", "total_displays": 0, "resource_type_link": "https://api.aweber.com/1.0/#web_form", "id": 2120561755}] diff --git a/tests/mock_adapter.py b/tests/mock_adapter.py new file mode 100644 index 0000000..2b938f3 --- /dev/null +++ b/tests/mock_adapter.py @@ -0,0 +1,43 @@ +from aweber_api import AWeberUser +import json +import os + +class MockAdapter(object): + + def __init__(self): + self.user = AWeberUser() + + request_paths = { + '/accounts' : 'accounts', + '/accounts/1' : 'account', + '/accounts/1/lists' : 'lists', + '/accounts/1?ws.op=getWebForms' : 'web_forms', + '/accounts/1/lists?ws.start=20&ws.size=20' : 'lists_page2', + '/accounts/1/lists/303449' : 'lists/303449', + '/accounts/1/lists/303449/campaigns' : 'lists/303449/campaigns' + } + + requests = [] + + def request(self, method, url, data={}): + if not (len(data.keys()) == 0): + first = True + for key in data.keys(): + if first: + url +='?' + else: + url +='&' + first = False + url += key+'='+str(data[key]) + + if not url in self.request_paths: + return '' + + path = "{0}{1}.json".format(self.data_dir, + self.request_paths[url]) + return json.load(open(path)) + + @property + def data_dir(self): + s = os.sep + return s.join(__file__.split(s)[:-1]+['data','']) diff --git a/tests/mock_adapter.pyc b/tests/mock_adapter.pyc new file mode 100644 index 0000000..4dd517e Binary files /dev/null and b/tests/mock_adapter.pyc differ diff --git a/tests/test_aweber_ b/tests/test_aweber_ new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_aweber_api.py b/tests/test_aweber_api.py new file mode 100644 index 0000000..ff26c44 --- /dev/null +++ b/tests/test_aweber_api.py @@ -0,0 +1,105 @@ +from unittest import TestCase +from mock_adapter import MockAdapter +from dingus import Dingus +from aweber_api import (AWeberAPI, AWeberUser, ACCESS_TOKEN_URL, AUTHORIZE_URL, + REQUEST_TOKEN_URL, AWeberEntry) + +key = 'XXXXX' +secret = '3434534534534' +class AWeberAPITest(TestCase): + + def setUp(self): + self.aweber = AWeberAPI(key, secret) + + def test_should_exist(self): + self.assertTrue(self.aweber) + +class WhenGettingARequestToken(AWeberAPITest): + + def setUp(self): + AWeberAPITest.setUp(self) + self.response = "oauth_token=1234&oauth_token_secret=abcd" + self.aweber.adapter = Dingus() + self.aweber.adapter.user = AWeberUser() + self.aweber.adapter.request = Dingus(return_value=self.response) + + def test_should_get_request_token(self): + token, secret = self.aweber.get_request_token('http://localhost/demo') + self.assertEqual(token, '1234') + self.assertEqual(secret, 'abcd') + + def test_should_pass_args_to_request(self): + self.called = False + def _request(method, url, params): + self.assertEqual(url, REQUEST_TOKEN_URL) + self.assertEqual(method, 'POST') + self.assertEqual(params['oauth_callback'], 'http://localhost/demo') + self.called = True + return self.response + self.aweber.adapter.request = _request + token, secret = self.aweber.get_request_token('http://localhost/demo') + self.assertTrue(self.called, 'Called _request') + + def test_should_set_up_user(self): + token, secret = self.aweber.get_request_token('http://localhost/demo') + + self.assertEqual(self.aweber.user.request_token, token) + self.assertEqual(self.aweber.user.token_secret, secret) + + def test_should_have_authorize_url(self): + token, secret = self.aweber.get_request_token('http://localhost/demo') + self.assertEqual(self.aweber.authorize_url, + "{0}?oauth_token={1}".format(AUTHORIZE_URL, token)) + + +class WhenGettingAnAccessToken(AWeberAPITest): + + def setUp(self): + AWeberAPITest.setUp(self) + self.response = "oauth_token=cheeseburger&oauth_token_secret=hotdog" + self.aweber.adapter = Dingus() + self.aweber.adapter.user = AWeberUser() + self.aweber.adapter.request = Dingus(return_value=self.response) + + self.aweber.user.request_token = '1234' + self.aweber.user.token_secret = 'abcd' + self.aweber.user.verifier = '234a35a1' + + + def test_should_get_access_token(self): + access_token, token_secret = self.aweber.get_access_token() + self.assertEqual(access_token, 'cheeseburger') + self.assertEqual(token_secret, 'hotdog') + + def test_should_pass_args_to_request(self): + self.called = False + def _request(method, url, params={}): + self.assertEqual(url, ACCESS_TOKEN_URL) + self.assertEqual(method, 'POST') + self.assertEqual(params['oauth_verifier'], '234a35a1') + self.called = True + return self.response + self.aweber.adapter.request = _request + token, secret = self.aweber.get_access_token() + self.assertTrue(self.called, 'Called _request') + + def test_should_set_up_user(self): + token, secret = self.aweber.get_access_token() + self.assertEqual(self.aweber.user.access_token, token) + self.assertEqual(self.aweber.user.token_secret, secret) + +class WhenGettingAnAccount(TestCase): + + def setUp(self): + self.aweber = AWeberAPI(key, secret) + self.aweber.adapter = MockAdapter() + + self.access_token = '1234' + self.token_secret = 'abcd' + + def test_when_getting_an_account(self): + account = self.aweber.get_account(self.access_token, self.token_secret) + self.assertEqual(type(account), AWeberEntry) + self.assertEqual(account.id, 910) + self.assertEqual(account.type, 'account') + diff --git a/tests/test_aweber_api.pyc b/tests/test_aweber_api.pyc new file mode 100644 index 0000000..4732a9d Binary files /dev/null and b/tests/test_aweber_api.pyc differ diff --git a/tests/test_aweber_collection.py b/tests/test_aweber_collection.py new file mode 100644 index 0000000..51bac1e --- /dev/null +++ b/tests/test_aweber_collection.py @@ -0,0 +1,37 @@ +from unittest import TestCase +from aweber_api import AWeberAPI, AWeberCollection, AWeberEntry +from mock_adapter import MockAdapter + + +class TestAWeberCollection(TestCase): + + def setUp(self): + self.aweber = AWeberAPI('1', '2') + self.aweber.adapter = MockAdapter() + self.lists = self.aweber.load_from_url('/accounts/1/lists') + + def test_should_be_a_collection(self): + self.assertTrue(type(self.lists), AWeberCollection) + + def test_should_have_24_lists(self): + self.assertTrue(len(self.lists), 24) + + def test_should_be_able_get_each_via_offset(self): + for i in range(0, 23): + list = self.lists[i] + self.assertEqual(type(list), AWeberEntry) + self.assertEqual(list.type, 'list') + + def test_should_be_able_to_iterate_on_collection(self): + list_number = 0 + for list in self.lists: + self.assertEqual(type(list), AWeberEntry) + self.assertEqual(list.type, 'list') + list_number += 1 + self.assertEqual(list_number, 24) + + def test_should_support_get_by_id(self): + list = self.lists.get_by_id(303449) + self.assertEqual(type(list), AWeberEntry) + self.assertEqual(list.type, 'list') + self.assertEqual(list.id, 303449) diff --git a/tests/test_aweber_collection.pyc b/tests/test_aweber_collection.pyc new file mode 100644 index 0000000..7b358b9 Binary files /dev/null and b/tests/test_aweber_collection.pyc differ diff --git a/tests/test_aweber_entry.py b/tests/test_aweber_entry.py new file mode 100644 index 0000000..dd7d6a6 --- /dev/null +++ b/tests/test_aweber_entry.py @@ -0,0 +1,63 @@ +from unittest import TestCase +from aweber_api import AWeberAPI, AWeberCollection, AWeberEntry +from mock_adapter import MockAdapter +import re + +class TestAWeberEntry(TestCase): + + def setUp(self): + self.aweber = AWeberAPI('1', '2') + self.aweber.adapter = MockAdapter() + self.list = self.aweber.load_from_url('/accounts/1/lists/303449') + + def test_should_be_an_entry(self): + self.assertEqual(type(self.list), AWeberEntry) + self.assertEqual(self.list.type, 'list') + + def test_should_have_id(self): + self.assertEqual(self.list.id, 303449) + + def test_should_have_other_properties(self): + self.assertEqual(self.list.name, 'default303449') + + def test_should_have_child_collections(self): + campaigns = self.list.campaigns + self.assertEqual(type(campaigns), AWeberCollection) + +class TestAWeberAccountEntry(TestCase): + + def setUp(self): + self.aweber = AWeberAPI('1', '2') + self.aweber.adapter = MockAdapter() + self.account = self.aweber.load_from_url('/accounts/1') + + def test_should_be_an_entry(self): + self.assertEqual(type(self.account), AWeberEntry) + self.assertEqual(self.account.type, 'account') + + def test_should_be_able_get_web_forms(self): + forms = self.account.get_web_forms() + +class TestAccountGetWebForms(TestAWeberAccountEntry): + + def setUp(self): + TestAWeberAccountEntry.setUp(self) + self.forms = self.account.get_web_forms() + + def test_should_be_a_list(self): + self.assertEqual(type(self.forms), list) + + def test_should_have_23_web_forms(self): + self.assertEqual(len(self.forms), 23) + + def test_each_should_be_entry(self): + for entry in self.forms: + self.assertEqual(type(entry), AWeberEntry) + self.assertEqual(entry.type, 'web_form') + + def test_each_should_have_correct_url(self): + url_regex = '/accounts\/1\/lists\/\d*/web_forms/\d*' + for entry in self.forms: + self.assertTrue(re.match(url_regex, entry.url)) + + diff --git a/tests/test_aweber_entry.pyc b/tests/test_aweber_entry.pyc new file mode 100644 index 0000000..a52c6ef Binary files /dev/null and b/tests/test_aweber_entry.pyc differ