diff --git a/laterpay/__init__.py b/laterpay/__init__.py index 6fe6105..2e3fc34 100644 --- a/laterpay/__init__.py +++ b/laterpay/__init__.py @@ -66,7 +66,8 @@ class ItemDefinition(object): For Single item purchases: http://docs.laterpay.net/platform/dialogs/buy/ """ - def __init__(self, item_id, pricing, url, title, expiry=None, sub_id=None, period=None, item_type=None): + def __init__(self, item_id, pricing, url, title, expiry=None, sub_id=None, + period=None, item_type=None, election_id=None): for price in pricing.split(','): if not _PRICING_RE.match(price): raise InvalidItemDefinition('Pricing is not valid: %s' % pricing) @@ -82,9 +83,16 @@ def __init__(self, item_id, pricing, url, title, expiry=None, sub_id=None, perio 'expiry': expiry, } - if item_type in {constants.ITEM_TYPE_CONTRIBUTION, constants.ITEM_TYPE_DONATION}: + if item_type in { + constants.ITEM_TYPE_CONTRIBUTION, + constants.ITEM_TYPE_DONATION, + constants.ITEM_TYPE_POLITICAL_CONTRIBUTION, + }: self.data['campaign_id'] = item_id self.item_type = item_type + + if item_type == constants.ITEM_TYPE_POLITICAL_CONTRIBUTION: + self.data['election_id'] = election_id else: self.data['article_id'] = item_id self.item_type = None @@ -320,6 +328,8 @@ def get_buy_url(self, item_definition, *args, **kwargs): page_type = 'contribute/pay_now' elif item_type == constants.ITEM_TYPE_DONATION: page_type = 'donate/pay_now' + elif item_type == constants.ITEM_TYPE_POLITICAL_CONTRIBUTION: + page_type = 'political_contribution/pay_now' else: page_type = 'buy' @@ -339,6 +349,8 @@ def get_add_url(self, item_definition, *args, **kwargs): page_type = 'contribute/pay_later' elif item_type == constants.ITEM_TYPE_DONATION: page_type = 'donate/pay_later' + elif item_type == constants.ITEM_TYPE_POLITICAL_CONTRIBUTION: + page_type = 'political_contribution/pay_later' else: page_type = 'add' diff --git a/laterpay/constants.py b/laterpay/constants.py index c96e6e9..cf919cb 100644 --- a/laterpay/constants.py +++ b/laterpay/constants.py @@ -14,3 +14,4 @@ ITEM_TYPE_CONTRIBUTION = 'contribution' ITEM_TYPE_DONATION = 'donation' +ITEM_TYPE_POLITICAL_CONTRIBUTION = 'political' diff --git a/tests/test_client.py b/tests/test_client.py index 3250e54..b37e458 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -72,6 +72,19 @@ def test_sub_id(self): 'url': 'http://example.com/t', }) + def test_election_id_for_non_poltical_contribution(self): + it = ItemDefinition( + 1, 'EUR20', 'http://example.com/t', 'title', item_type=constants.ITEM_TYPE_CONTRIBUTION, + election_id='123-election', + ) + self.assertEqual(it.data, { + 'campaign_id': 1, + 'expiry': None, + 'pricing': 'EUR20', + 'title': 'title', + 'url': 'http://example.com/t', + }) + def test_item_type_contribution(self): it = ItemDefinition(1, 'EUR20', 'http://example.com/t', 'title', item_type=constants.ITEM_TYPE_CONTRIBUTION) self.assertEqual(it.data, { @@ -94,6 +107,21 @@ def test_item_type_donation(self): }) self.assertEqual(it.item_type, 'donation') + def test_item_type_political_contribution(self): + it = ItemDefinition( + 1, 'EUR20', 'http://example.com/t', 'title', item_type=constants.ITEM_TYPE_POLITICAL_CONTRIBUTION, + election_id='123-election', + ) + self.assertEqual(it.data, { + 'campaign_id': 1, + 'expiry': None, + 'pricing': 'EUR20', + 'title': 'title', + 'url': 'http://example.com/t', + 'election_id': '123-election', + }) + self.assertEqual(it.item_type, 'political') + def test_item_type_unknown(self): it = ItemDefinition(1, 'EUR20', 'http://example.com/t', 'title', item_type='whatever') self.assertEqual(it.data, { @@ -114,33 +142,36 @@ def setUp(self): 'some-secret') self.item = ItemDefinition(1, 'EUR20', 'http://example.com/', 'title') - def assertQueryString(self, url, key, value=None): + def assertQueryString(self, url, key, value, msg=None): + d = parse_qs(urlparse(url).query) + self.assertIn(key, d, msg=msg) + + if not isinstance(value, list): + value = [value] + self.assertEqual(d[key], value, msg=msg) + + def assertNotQueryString(self, url, key, msg=None): d = parse_qs(urlparse(url).query) - if not value: - return (key in d) - return d.get(key, None) == value + self.assertNotIn(key, d, msg=msg) def test_get_web_url_itemdefinition_value_none(self): # item with expiry not set. item = ItemDefinition(1, 'EUR20', 'http://help.me/', 'title') url = self.lp._get_web_url(item, 'PAGE_TYPE') - self.assertFalse( - self.assertQueryString(url, 'expiry'), - 'expiry url param is "None". Should be omitted.' - ) + self.assertNotQueryString(url, 'expiry', msg='expiry url param is "None". Should be omitted.') def test_web_url_product_key(self): # Default url = self.lp._get_web_url(self.item, 'PAGE_TYPE') - self.assertFalse(self.assertQueryString(url, 'product_key')) + self.assertNotQueryString(url, 'product') # Enabled url = self.lp._get_web_url(self.item, 'PAGE_TYPE', product_key='foobar') - self.assertQueryString(url, 'product_key', value='foobar') + self.assertQueryString(url, 'product', 'foobar') # Disabled url = self.lp._get_web_url(self.item, 'PAGE_TYPE', product_key=None) - self.assertFalse(self.assertQueryString(url, 'product_key')) + self.assertNotQueryString(url, 'product') def test_web_url_dialog(self): # Default @@ -158,24 +189,24 @@ def test_web_url_dialog(self): def test_web_url_jsevents(self): # Default url = self.lp._get_web_url(self.item, 'PAGE_TYPE') - self.assertFalse(self.assertQueryString(url, 'jsevents')) + self.assertNotQueryString(url, 'jsevents') # Enabled url = self.lp._get_web_url(self.item, 'PAGE_TYPE', use_jsevents=True) - self.assertQueryString(url, 'jsevents', value='1') + self.assertQueryString(url, 'jsevents', '1') # Disabled url = self.lp._get_web_url(self.item, 'PAGE_TYPE', use_jsevents=False) - self.assertFalse(self.assertQueryString(url, 'jsevents')) + self.assertNotQueryString(url, 'jsevents') def test_web_url_transaction_reference(self): # Default url = self.lp._get_web_url(self.item, 'PAGE_TYPE') - self.assertFalse(self.assertQueryString(url, 'transaction_reference')) + self.assertNotQueryString(url, 'tref') # Valid url = self.lp._get_web_url(self.item, 'PAGE_TYPE', transaction_reference='loremipsum') - self.assertQueryString(url, 'transaction_reference', value='loremipsum') + self.assertQueryString(url, 'tref', 'loremipsum') # Invalid with self.assertRaises(APIException): @@ -184,54 +215,54 @@ def test_web_url_transaction_reference(self): def test_web_url_consumable(self): # Default url = self.lp._get_web_url(self.item, 'PAGE_TYPE') - self.assertFalse(self.assertQueryString(url, 'consumable')) + self.assertNotQueryString(url, 'consumable') # Enabled url = self.lp._get_web_url(self.item, 'PAGE_TYPE', consumable=True) - self.assertQueryString(url, 'consumable', value='1') + self.assertQueryString(url, 'consumable', '1') # Disabled url = self.lp._get_web_url(self.item, 'PAGE_TYPE', consumable=False) - self.assertFalse(self.assertQueryString(url, 'consumable')) + self.assertNotQueryString(url, 'consumable') def test_web_url_return_url(self): # Default url = self.lp._get_web_url(self.item, 'PAGE_TYPE') - self.assertFalse(self.assertQueryString(url, 'return_url')) + self.assertNotQueryString(url, 'return_url') # Given url = self.lp._get_web_url(self.item, 'PAGE_TYPE', return_url='http://example.com/foo?foo=bar&lorem=ipsum') - self.assertQueryString(url, 'return_url', value='http://example.com/foo?foo=bar&lorem=ipsum') + self.assertQueryString(url, 'return_url', 'http://example.com/foo?foo=bar&lorem=ipsum') # Omitted url = self.lp._get_web_url(self.item, 'PAGE_TYPE', return_url=None) - self.assertFalse(self.assertQueryString(url, 'return_url')) + self.assertNotQueryString(url, 'return_url') def test_web_url_failure_url(self): # Default url = self.lp._get_web_url(self.item, 'PAGE_TYPE') - self.assertFalse(self.assertQueryString(url, 'failure_url')) + self.assertNotQueryString(url, 'failure_url') # Given url = self.lp._get_web_url(self.item, 'PAGE_TYPE', failure_url='http://example.com/foo?foo=bar&lorem=ipsum') - self.assertQueryString(url, 'failure_url', value='http://example.com/foo?foo=bar&lorem=ipsum') + self.assertQueryString(url, 'failure_url', 'http://example.com/foo?foo=bar&lorem=ipsum') # Omitted url = self.lp._get_web_url(self.item, 'PAGE_TYPE', failure_url=None) - self.assertFalse(self.assertQueryString(url, 'failure_url')) + self.assertNotQueryString(url, 'failure_url') def test_web_url_muid(self): # Default url = self.lp._get_web_url(self.item, 'PAGE_TYPE') - self.assertFalse(self.assertQueryString(url, 'muid')) + self.assertNotQueryString(url, 'muid') # Given url = self.lp._get_web_url(self.item, 'PAGE_TYPE', muid='0zA9-aZ09-0A9z') - self.assertQueryString(url, 'muid', value='0zA9-aZ09-0A9z') + self.assertQueryString(url, 'muid', '0zA9-aZ09-0A9z') # Omitted url = self.lp._get_web_url(self.item, 'PAGE_TYPE', muid=None) - self.assertFalse(self.assertQueryString(url, 'muid')) + self.assertNotQueryString(url, 'muid') def test_get_add_url(self): item = ItemDefinition(1, 'EUR20', 'http://example.net/t', 'title') @@ -248,20 +279,17 @@ def test_get_add_url(self): something='else', BLUB=[u'u2', b'b1', b'b2', u'u1'], ) - self.assertFalse( - self.assertQueryString(url, 'expiry'), - 'expiry url param is "None". Should be omitted.' - ) - self.assertQueryString(url, 'product_key', value='some-product-key') + self.assertNotQueryString(url, 'expiry', msg='expiry url param is "None". Should be omitted.') + self.assertQueryString(url, 'product', 'some-product-key') self.assertTrue(url.startswith('https://web.laterpay.net/add?')) - self.assertQueryString(url, 'use_jsevents', value='1') - self.assertQueryString(url, 'transaction_reference', value='TX-REF') - self.assertQueryString(url, 'consumable', value='1') - self.assertQueryString(url, 'return_url', value='http://return.url/foo?bar=buz&lorem=ipsum') - self.assertQueryString(url, 'failure_url', value='http://failure.url/FOO?BAR=BUZ&LOREM=IPSUM') - self.assertQueryString(url, 'muid', value='someone') - self.assertQueryString(url, 'something', value='else') - self.assertQueryString(url, 'BLUB', value=[b'b1', 'b2', u'u1', 'u2']) + self.assertQueryString(url, 'jsevents', '1') + self.assertQueryString(url, 'tref', 'TX-REF') + self.assertQueryString(url, 'consumable', '1') + self.assertQueryString(url, 'return_url', 'http://return.url/foo?bar=buz&lorem=ipsum') + self.assertQueryString(url, 'failure_url', 'http://failure.url/FOO?BAR=BUZ&LOREM=IPSUM') + self.assertQueryString(url, 'muid', 'someone') + self.assertQueryString(url, 'something', 'else') + self.assertQueryString(url, 'BLUB', ['u2', 'b1', 'b2', 'u1']) def test_get_add_url_contribution(self): item = ItemDefinition( @@ -269,10 +297,10 @@ def test_get_add_url_contribution(self): ) url = self.lp.get_add_url(item, item_type='contribution') self.assertTrue(url.startswith('https://web.laterpay.net/dialog/contribute/pay_later?')) - self.assertQueryString(url, 'campaign_id', value='2') - self.assertQueryString(url, 'pricing', value='EUR20') - self.assertQueryString(url, 'url', value='http://example.net/t') - self.assertQueryString(url, 'title', value='Save the World!') + self.assertQueryString(url, 'campaign_id', '2') + self.assertQueryString(url, 'pricing', 'EUR20') + self.assertQueryString(url, 'url', 'http://example.net/t') + self.assertQueryString(url, 'title', 'Save the World!') def test_get_add_url_donation(self): item = ItemDefinition( @@ -280,10 +308,23 @@ def test_get_add_url_donation(self): ) url = self.lp.get_add_url(item, item_type='donation') self.assertTrue(url.startswith('https://web.laterpay.net/dialog/donate/pay_later?')) - self.assertQueryString(url, 'campaign_id', value='2') - self.assertQueryString(url, 'pricing', value='EUR20') - self.assertQueryString(url, 'url', value='http://example.net/t') - self.assertQueryString(url, 'title', value='Save the World!') + self.assertQueryString(url, 'campaign_id', '2') + self.assertQueryString(url, 'pricing', 'EUR20') + self.assertQueryString(url, 'url', 'http://example.net/t') + self.assertQueryString(url, 'title', 'Save the World!') + + def test_get_add_url_political_contribution(self): + item = ItemDefinition( + '2', 'EUR20', 'http://example.net/t', 'Vote for Sue!', + item_type=constants.ITEM_TYPE_POLITICAL_CONTRIBUTION, election_id='123-election', + ) + url = self.lp.get_add_url(item, item_type='political') + self.assertTrue(url.startswith('https://web.laterpay.net/dialog/political_contribution/pay_later?')) + self.assertQueryString(url, 'campaign_id', '2') + self.assertQueryString(url, 'pricing', 'EUR20') + self.assertQueryString(url, 'url', 'http://example.net/t') + self.assertQueryString(url, 'title', 'Vote for Sue!') + self.assertQueryString(url, 'election_id', '123-election') def test_get_buy_url(self): item = ItemDefinition(1, 'EUR20', 'http://example.net/t', 'title') @@ -300,20 +341,17 @@ def test_get_buy_url(self): something='else', BLUB=[u'u2', b'b1', b'b2', u'u1'], ) - self.assertFalse( - self.assertQueryString(url, 'expiry'), - 'expiry url param is "None". Should be omitted.' - ) - self.assertQueryString(url, 'product_key', value='some-product-key') + self.assertNotQueryString(url, 'expiry', msg='expiry url param is "None". Should be omitted.') + self.assertQueryString(url, 'product', 'some-product-key') self.assertTrue(url.startswith('https://web.laterpay.net/buy?')) - self.assertQueryString(url, 'use_jsevents', value='1') - self.assertQueryString(url, 'transaction_reference', value='TX-REF') - self.assertQueryString(url, 'consumable', value='1') - self.assertQueryString(url, 'return_url', value='http://return.url/foo?bar=buz&lorem=ipsum') - self.assertQueryString(url, 'failure_url', value='http://failure.url/FOO?BAR=BUZ&LOREM=IPSUM') - self.assertQueryString(url, 'muid', value='someone') - self.assertQueryString(url, 'something', value='else') - self.assertQueryString(url, 'BLUB', value=[b'b1', 'b2', u'u1', 'u2']) + self.assertQueryString(url, 'jsevents', '1') + self.assertQueryString(url, 'tref', 'TX-REF') + self.assertQueryString(url, 'consumable', '1') + self.assertQueryString(url, 'return_url', 'http://return.url/foo?bar=buz&lorem=ipsum') + self.assertQueryString(url, 'failure_url', 'http://failure.url/FOO?BAR=BUZ&LOREM=IPSUM') + self.assertQueryString(url, 'muid', 'someone') + self.assertQueryString(url, 'something', 'else') + self.assertQueryString(url, 'BLUB', ['u2', 'b1', 'b2', 'u1']) def test_get_buy_url_contribution(self): item = ItemDefinition( @@ -322,10 +360,10 @@ def test_get_buy_url_contribution(self): ) url = self.lp.get_buy_url(item) self.assertTrue(url.startswith('https://web.laterpay.net/dialog/contribute/pay_now?')) - self.assertQueryString(url, 'campaign_id', value='2') - self.assertQueryString(url, 'pricing', value='EUR20') - self.assertQueryString(url, 'url', value='http://example.net/t') - self.assertQueryString(url, 'title', value='Save the World!') + self.assertQueryString(url, 'campaign_id', 'save-the-world') + self.assertQueryString(url, 'pricing', 'EUR20') + self.assertQueryString(url, 'url', 'http://example.net/t') + self.assertQueryString(url, 'title', 'Save the World!') def test_get_buy_url_donation(self): item = ItemDefinition( @@ -334,10 +372,23 @@ def test_get_buy_url_donation(self): ) url = self.lp.get_buy_url(item) self.assertTrue(url.startswith('https://web.laterpay.net/dialog/donate/pay_now?')) - self.assertQueryString(url, 'campaign_id', value='2') - self.assertQueryString(url, 'pricing', value='EUR20') - self.assertQueryString(url, 'url', value='http://example.net/t') - self.assertQueryString(url, 'title', value='Save the World!') + self.assertQueryString(url, 'campaign_id', 'save-the-world') + self.assertQueryString(url, 'pricing', 'EUR20') + self.assertQueryString(url, 'url', 'http://example.net/t') + self.assertQueryString(url, 'title', 'Save the World!') + + def test_get_buy_url_political_contribution(self): + item = ItemDefinition( + 'vote-for-sue', 'EUR20', 'http://example.net/t', 'Vote for Sue!', + item_type=constants.ITEM_TYPE_POLITICAL_CONTRIBUTION, election_id='123-election', + ) + url = self.lp.get_buy_url(item) + self.assertTrue(url.startswith('https://web.laterpay.net/dialog/political_contribution/pay_now?')) + self.assertQueryString(url, 'campaign_id', 'vote-for-sue') + self.assertQueryString(url, 'pricing', 'EUR20') + self.assertQueryString(url, 'url', 'http://example.net/t') + self.assertQueryString(url, 'title', 'Vote for Sue!') + self.assertQueryString(url, 'election_id', '123-election') def test_get_subscribe_url(self): item = ItemDefinition(1, 'EUR20', 'http://example.net/t', 'title', sub_id='a0_-9Z', period=12345) @@ -352,19 +403,16 @@ def test_get_subscribe_url(self): period=12345, BLUB=[u'u2', b'b1', b'b2', u'u1'], ) - self.assertFalse( - self.assertQueryString(url, 'expiry'), - 'expiry url param is "None". Should be omitted.' - ) - self.assertQueryString(url, 'sub_id', value='a0_-9Z') - self.assertQueryString(url, 'product_key', value='some-product-key') + self.assertNotQueryString(url, 'expiry', msg='expiry url param is "None". Should be omitted.') + self.assertQueryString(url, 'sub_id', 'a0_-9Z') + self.assertQueryString(url, 'product', 'some-product-key') self.assertTrue(url.startswith('https://web.laterpay.net/subscribe?')) - self.assertQueryString(url, 'return_url', value='http://return.url/foo?bar=buz&lorem=ipsum') - self.assertQueryString(url, 'failure_url', value='http://failure.url/FOO?BAR=BUZ&LOREM=IPSUM') - self.assertQueryString(url, 'muid', value='someone') - self.assertQueryString(url, 'something', value='else') - self.assertQueryString(url, 'period', value='12345') - self.assertQueryString(url, 'BLUB', value=[b'b1', 'b2', u'u1', 'u2']) + self.assertQueryString(url, 'return_url', 'http://return.url/foo?bar=buz&lorem=ipsum') + self.assertQueryString(url, 'failure_url', 'http://failure.url/FOO?BAR=BUZ&LOREM=IPSUM') + self.assertQueryString(url, 'muid', 'someone') + self.assertQueryString(url, 'something', 'else') + self.assertQueryString(url, 'period', '12345') + self.assertQueryString(url, 'BLUB', ['u2', 'b1', 'b2', 'u1']) def test_get_login_dialog_url_with_use_dialog_api_false(self): url = self.lp.get_login_dialog_url('http://example.org')