From f93dacdb2df8c569c4be080a9c11c8fbbad15d21 Mon Sep 17 00:00:00 2001 From: Bruno Vieira Date: Thu, 28 Sep 2023 10:28:44 +0100 Subject: [PATCH] add support for cursor based pagination Signed-off-by: Bruno Vieira --- CHANGELOG.md | 15 ++ README.md | 8 +- chartmogul/api/activity.py | 8 +- chartmogul/api/contact.py | 3 +- chartmogul/api/customer.py | 4 +- chartmogul/api/customers/activity.py | 6 +- chartmogul/api/customers/subscription.py | 21 +- chartmogul/api/invoice.py | 4 +- chartmogul/api/plan.py | 7 +- chartmogul/api/plan_group.py | 6 +- chartmogul/api/plan_group_plans.py | 6 +- chartmogul/api/subscription_event.py | 6 +- chartmogul/version.py | 2 +- test/api/test_activity.py | 9 +- test/api/test_contact.py | 4 +- test/api/test_customer.py | 236 ++++++++++++------- test/api/test_customers/test_activity.py | 5 +- test/api/test_customers/test_subscription.py | 9 +- test/api/test_invoice.py | 230 ++++++++++++------ test/api/test_plan.py | 33 ++- test/api/test_plan_group.py | 88 ++++++- test/api/test_subscription.py | 7 +- test/api/test_subscription_event.py | 87 ++++--- 23 files changed, 561 insertions(+), 243 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..c91637d --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,15 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog], +and this project adheres to [Semantic Versioning]. + +[Keep a Changelog]: https://keepachangelog.com/en/1.0.0/ +[Semantic Versioning]: https://semver.org/spec/v2.0.0.html + +## [3.1.3] - 2023-09-27 + +### Added +- Support for cursor based pagination to `.all()` endpoints. +- Changelog. diff --git a/README.md b/README.md index 370d862..f197fff 100644 --- a/README.md +++ b/README.md @@ -119,7 +119,7 @@ chartmogul.DataSource.destroy(config, uuid='ds_5915ee5a-babd-406b-b8ce-d207133fb ```python chartmogul.Customer.create(config, data={}) -chartmogul.Customer.all(config, page=2, per_page=20) +chartmogul.Customer.all(config, cursor='cursor==', per_page=20) chartmogul.Customer.retrieve(config, uuid='cus_5915ee5a-babd-406b-b8ce-d207133fb4cb') chartmogul.Customer.search(config, email='email@email.com') chartmogul.Customer.merge(config, data={ @@ -217,7 +217,7 @@ chartmogul.Plan.retrieve(config, uuid='cus_5915ee5a-babd-406b-b8ce-d207133fb4cb' chartmogul.Plan.modify(config, uuid='cus_5915ee5a-babd-406b-b8ce-d207133fb4cb', data={ 'name': 'new name' }) -chartmogul.Plan.all(config, page=2, external_id='') +chartmogul.Plan.all(config, cursor='cursor==', external_id='') chartmogul.Plan.destroy(config, uuid='') ``` @@ -227,7 +227,7 @@ chartmogul.Plan.destroy(config, uuid='') chartmogul.PlanGroup.create(config, data={}) chartmogul.PlanGroup.retrieve(config, uuid='plg_5915ee5a-babd-406b-b8ce-d207133fb4cb') chartmogul.PlanGroup.modify(config, uuid='plg_5915ee5a-babd-406b-b8ce-d207133fb4cb', data={}) -chartmogul.PlanGroup.all(config, page=2) +chartmogul.PlanGroup.all(config, cursor='cursor==') chartmogul.PlanGroup.all(config, uuid='plg_5915ee5a-babd-406b-b8ce-d207133fb4cb') chartmogul.PlanGroup.destroy(config, uuid='') ``` @@ -238,7 +238,7 @@ chartmogul.PlanGroup.destroy(config, uuid='') import chartmogul chartmogul.Invoice.create(config, uuid='cus_5915ee5a-babd-406b-b8ce-d207133fb4cb', data={}) -chartmogul.Invoice.all(config, uuid='cus_5915ee5a-babd-406b-b8ce-d207133fb4cb', page=2, per_page=10) +chartmogul.Invoice.all(config, uuid='cus_5915ee5a-babd-406b-b8ce-d207133fb4cb', cursor='cursor==', per_page=10) chartmogul.Invoice.all(config, customer_uuid='cus_f466e33d-ff2b-4a11-8f85-417eb02157a7', external_id='INV0001') chartmogul.Invoice.retrieve(config, uuid='inv_22910fc6-c931-48e7-ac12-90d2cb5f0059') ``` diff --git a/chartmogul/api/activity.py b/chartmogul/api/activity.py index 1e599a2..172860b 100644 --- a/chartmogul/api/activity.py +++ b/chartmogul/api/activity.py @@ -5,11 +5,13 @@ class Activity(Resource): """ - https://dev.chartmogul.com/v1.0/reference#list-customer-subscriptions + https://dev.chartmogul.com/reference/list-activities """ - _path = "/activities" + _path = '/activities' _root_key = 'entries' - _many = namedtuple('Activities', [_root_key, "has_more", "per_page"]) + _many = namedtuple('Activities', + [_root_key, 'has_more', 'per_page', 'cursor'], + defaults=[None, None, None]) class _Schema(Schema): activity_arr = fields.Number(data_key='activity-arr') diff --git a/chartmogul/api/contact.py b/chartmogul/api/contact.py index c381026..f7a1456 100644 --- a/chartmogul/api/contact.py +++ b/chartmogul/api/contact.py @@ -9,8 +9,7 @@ class Contact(Resource): """ _path = "/contacts{/uuid}" _root_key = "entries" - _many = namedtuple("Contacts", - [_root_key, "has_more", "cursor"]) + _many = namedtuple("Contacts", [_root_key, "has_more", "cursor"]) class _Schema(Schema): uuid = fields.String() diff --git a/chartmogul/api/customer.py b/chartmogul/api/customer.py index 5fd3697..2657a31 100644 --- a/chartmogul/api/customer.py +++ b/chartmogul/api/customer.py @@ -32,7 +32,9 @@ class Customer(Resource): _path = "/customers{/uuid}" _root_key = 'entries' _many = namedtuple('Customers', - [_root_key, "has_more", "per_page", "page", "current_page", "total_pages"]) + [_root_key, "has_more", "per_page", "page", + "current_page", "total_pages", "cursor"], + defaults=[None, None, None, None, None, None]) class _Schema(Schema): # All operations diff --git a/chartmogul/api/customers/activity.py b/chartmogul/api/customers/activity.py index b77f76f..d9d51e8 100644 --- a/chartmogul/api/customers/activity.py +++ b/chartmogul/api/customers/activity.py @@ -7,9 +7,11 @@ class CustomerActivity(Resource): """ https://dev.chartmogul.com/v1.0/reference#list-customer-subscriptions """ - _path = "/customers{/uuid}/activities" + _path = '/customers{/uuid}/activities' _root_key = 'entries' - _many = namedtuple('Activities', [_root_key, "has_more", "per_page", "page"]) + _many = namedtuple('Activities', + [_root_key, 'has_more', 'per_page', 'page', 'cursor'], + defaults=[None, None, None, None]) class _Schema(Schema): id = fields.Int() diff --git a/chartmogul/api/customers/subscription.py b/chartmogul/api/customers/subscription.py index cfc1331..12dc910 100644 --- a/chartmogul/api/customers/subscription.py +++ b/chartmogul/api/customers/subscription.py @@ -8,9 +8,11 @@ class CustomerSubscription(Resource): https://dev.chartmogul.com/v1.0/reference#list-customer-subscriptions https://dev.chartmogul.com/v1.0/reference#list-a-customers-subscriptions """ - _path = "/customers{/uuid}/subscriptions" + _path = '/customers{/uuid}/subscriptions' _root_key = 'entries' - _many = namedtuple('Subscriptions', [_root_key, "has_more", "per_page", "page"]) + _many = namedtuple('Subscriptions', + [_root_key, 'has_more', 'per_page', 'page', 'cursor'], + defaults=[None, None, None, None]) class _Schema(Schema): id = fields.Int(allow_none=True) @@ -45,11 +47,16 @@ def make(self, data, **kwargs): @classmethod def _loadJSON(cls, jsonObj): if "subscriptions" in jsonObj: - _many = namedtuple('Subscriptions', ["subscriptions", "current_page", "total_pages", "customer_uuid"]) - return _many(cls._schema.load(jsonObj["subscriptions"], many=True), - jsonObj["current_page"], - jsonObj["total_pages"], - jsonObj["customer_uuid"]) + _many = namedtuple( + 'Subscriptions', + ["subscriptions", "current_page", "total_pages", "customer_uuid", "has_more", "cursor"] + ) + return _many(cls._schema.load(jsonObj['subscriptions'], many=True), + current_page=jsonObj.get('current_page', None), + total_pages=jsonObj.get('total_pages', None), + customer_uuid=jsonObj.get('customer_uuid', None), + has_more=jsonObj.get('has_more', None), + cursor=jsonObj.get('cursor', None)) else: return super(CustomerSubscription, cls)._loadJSON(jsonObj) diff --git a/chartmogul/api/invoice.py b/chartmogul/api/invoice.py index 342f083..5f45d75 100644 --- a/chartmogul/api/invoice.py +++ b/chartmogul/api/invoice.py @@ -40,7 +40,9 @@ class Invoice(Resource): """ _path = "/import/customers{/uuid}/invoices" _root_key = 'invoices' - _many = namedtuple('Invoices', [_root_key, "current_page", "total_pages", "customer_uuid"]) + _many = namedtuple('Invoices', + [_root_key, "current_page", "total_pages", "cursor", "has_more", "customer_uuid"], + defaults=[None, None, None, None, None]) _many.__new__.__defaults__ = (None,) * len(_many._fields) class _Schema(Schema): diff --git a/chartmogul/api/plan.py b/chartmogul/api/plan.py index a82fd38..301da06 100644 --- a/chartmogul/api/plan.py +++ b/chartmogul/api/plan.py @@ -7,9 +7,12 @@ class Plan(Resource): """ https://dev.chartmogul.com/v1.0/reference#plans """ - _path = "/plans{/uuid}" + _path = '/plans{/uuid}' _root_key = 'plans' - _many = namedtuple('Plans', [_root_key, "current_page", "total_pages"]) + _many = namedtuple( + 'Plans', + [_root_key, 'current_page', 'total_pages', 'has_more', 'cursor'], + defaults=[None, None, None, None]) class _Schema(Schema): uuid = fields.String() diff --git a/chartmogul/api/plan_group.py b/chartmogul/api/plan_group.py index ef9f015..c5b5de0 100644 --- a/chartmogul/api/plan_group.py +++ b/chartmogul/api/plan_group.py @@ -8,9 +8,11 @@ class PlanGroup(Resource): """ https://dev.chartmogul.com/v1.0/reference#plan_groups """ - _path = "/plan_groups{/uuid}" + _path = '/plan_groups{/uuid}' _root_key = 'plan_groups' - _many = namedtuple('PlanGroups', [_root_key, "current_page", "total_pages"]) + _many = namedtuple('PlanGroups', + [_root_key, 'current_page', 'total_pages', 'has_more', 'cursor'], + defaults=[None, None, None, None]) class _Schema(Schema): uuid = fields.String() diff --git a/chartmogul/api/plan_group_plans.py b/chartmogul/api/plan_group_plans.py index b4250cd..2690731 100644 --- a/chartmogul/api/plan_group_plans.py +++ b/chartmogul/api/plan_group_plans.py @@ -7,9 +7,11 @@ class PlanGroupPlans(Resource): """ https://dev.chartmogul.com/v1.0/reference#plan_groups """ - _path = "/plan_groups{/uuid}/plans" + _path = '/plan_groups{/uuid}/plans' _root_key = 'plans' - _many = namedtuple('PlanGroupPlans', [_root_key, "current_page", "total_pages"]) + _many = namedtuple('PlanGroupPlans', + [_root_key, 'current_page', 'total_pages', 'has_more', 'cursor'], + defaults=[None, None, None, None]) class _Schema(Schema): uuid = fields.String() diff --git a/chartmogul/api/subscription_event.py b/chartmogul/api/subscription_event.py index 75e2455..de1375b 100644 --- a/chartmogul/api/subscription_event.py +++ b/chartmogul/api/subscription_event.py @@ -7,9 +7,11 @@ class SubscriptionEvent(Resource): """ https://dev.chartmogul.com/reference/subscription-events """ - _path = "/subscription_events" + _path = '/subscription_events' _root_key = 'subscription_events' - _many = namedtuple('SubscriptionEvents', [_root_key, 'meta']) + _many = namedtuple('SubscriptionEvents', + [_root_key, 'meta', 'has_more', 'cursor'], + defaults=[None, None, None]) class _Schema(Schema): id = fields.Int(required=True) diff --git a/chartmogul/version.py b/chartmogul/version.py index f71b21a..dc0a25b 100644 --- a/chartmogul/version.py +++ b/chartmogul/version.py @@ -1 +1 @@ -__version__ = '3.1.2' +__version__ = '3.1.3' diff --git a/test/api/test_activity.py b/test/api/test_activity.py index c7573bd..56f936d 100644 --- a/test/api/test_activity.py +++ b/test/api/test_activity.py @@ -36,14 +36,17 @@ def test_all(self, mock_requests): "uuid": "f1a49735-21c7-4e3f-9ddc-67927aaadcf4" }, ], - "has_more":False, - "per_page":200, + "has_more": False, + "per_page": 200, + "cursor": "cursor==" } ) config = Config("token") # is actually checked in mock result = Activity.all(config).get() - self.assertEqual(mock_requests.call_count, 1, "expected call") + self.assertEqual(mock_requests.call_count, 1, 'expected call') self.assertEqual(mock_requests.last_request.qs, {}) self.assertEqual(result.__class__.__name__, Activity._many.__name__) self.assertEqual(result.entries[0].uuid, 'f1a49735-21c7-4e3f-9ddc-67927aaadcf4') + self.assertFalse(result.has_more) + self.assertEqual(result.cursor, 'cursor==') diff --git a/test/api/test_contact.py b/test/api/test_contact.py index b9e5e9b..881c119 100644 --- a/test/api/test_contact.py +++ b/test/api/test_contact.py @@ -45,7 +45,7 @@ allContacts = { "entries": [contact], - "cursor": "MjAyMy0wMy0xMFQwMzo1MzoxNS44MTg1MjUwMDArMDA6MDAmY29uXzE2NDcwZjk4LWJlZjctMTFlZC05MjA4LTdiMDhhNDBmMzA0OQ==", + "cursor": "cursor==", "has_more": False } @@ -77,6 +77,8 @@ def test_all(self, mock_requests): self.assertEqual(mock_requests.last_request.text, None) self.assertEqual(dir(contacts), dir(expected)) self.assertTrue(isinstance(contacts.entries[0], Contact)) + self.assertFalse(contacts.has_more) + self.assertEqual(contacts.cursor, "cursor==") @requests_mock.mock() def test_create(self, mock_requests): diff --git a/test/api/test_customer.py b/test/api/test_customer.py index 358d6f3..81b344c 100644 --- a/test/api/test_customer.py +++ b/test/api/test_customer.py @@ -7,89 +7,94 @@ from pprint import pprint -docsListSample = { - "entries": [ - { - "id": 25647, - "uuid": "cus_de305d54-75b4-431b-adb2-eb6b9e546012", - "external_id": "34916129", - "external_ids": ["34916129"], - "data_source_uuid": "ds_610b7a84-c50f-11e6-8aab-97d6db98913a", - "data_source_uuids": ["ds_610b7a84-c50f-11e6-8aab-97d6db98913a"], - "name": "Example Company", - "company": "", - "email": "bob@examplecompany.com", - "status": "Active", - "lead_created_at": "2015-01-01T10:00:00-04:00", - "free_trial_started_at": "2015-01-09T10:00:00-04:00", - "customer-since": "2015-06-09T13:16:00-04:00", - "city": "Nowhereville", - "state": "Alaska", - "country": "US", - "zip": "0185128", - "attributes":{ - "tags": ["engage", "unit loss", "discountable"], - "stripe":{ - "uid": 7, - "coupon": True +entry = { + "id": 25647, + "uuid": "cus_de305d54-75b4-431b-adb2-eb6b9e546012", + "external_id": "34916129", + "external_ids": ["34916129"], + "data_source_uuid": "ds_610b7a84-c50f-11e6-8aab-97d6db98913a", + "data_source_uuids": ["ds_610b7a84-c50f-11e6-8aab-97d6db98913a"], + "name": "Example Company", + "company": "", + "email": "bob@examplecompany.com", + "status": "Active", + "lead_created_at": "2015-01-01T10:00:00-04:00", + "free_trial_started_at": "2015-01-09T10:00:00-04:00", + "customer-since": "2015-06-09T13:16:00-04:00", + "city": "Nowhereville", + "state": "Alaska", + "country": "US", + "zip": "0185128", + "attributes":{ + "tags": ["engage", "unit loss", "discountable"], + "stripe":{ + "uid": 7, + "coupon": True + }, + "clearbit": { + "company": { + "name": "Example Company", + "legalName": "Example Company Inc.", + "domain": "examplecompany.com", + "url": "http://examplecompany.com", + "category": { + "sector": "Information Technology", + "industryGroup": "Software and Services", + "industry": "Software", + "subIndustry": "Application Software" }, - "clearbit": { - "company": { - "name": "Example Company", - "legalName": "Example Company Inc.", - "domain": "examplecompany.com", - "url": "http://examplecompany.com", - "category": { - "sector": "Information Technology", - "industryGroup": "Software and Services", - "industry": "Software", - "subIndustry": "Application Software" - }, - "metrics": { - "raised": 1502450000, - "employees": 1000, - "googleRank": 7, - "alexaGlobalRank": 2319, - "marketCap": None - }, - }, - "person": { - "name": { - "fullName": "Bob Kramer" - }, - "employment": { - "name": "Example Company" - } - } + "metrics": { + "raised": 1502450000, + "employees": 1000, + "googleRank": 7, + "alexaGlobalRank": 2319, + "marketCap": None }, - "custom": { - "CAC": 213, - "utmCampaign": "social media 1", - "convertedAt": "2015-09-08 00:00:00", - "pro": False, - "salesRep": "Gabi" - } - }, - "address": { - "address_zip": "0185128", - "city": "Nowhereville", - "country": "US", - "state": "Alaska" }, - "mrr": 3000.0, - "arr": 36000.0, - "billing-system-url": "https:\/\/dashboard.stripe.com\/customers\/cus_4Z2ZpyJFuQ0XMb", - "chartmogul-url": "https:\/\/app.chartmogul.com\/#customers\/25647-Example_Company", - "billing-system-type": "Stripe", - "currency": "USD", - "currency-sign": "$" + "person": { + "name": { + "fullName": "Bob Kramer" + }, + "employment": { + "name": "Example Company" + } + } + }, + "custom": { + "CAC": 213, + "utmCampaign": "social media 1", + "convertedAt": "2015-09-08 00:00:00", + "pro": False, + "salesRep": "Gabi" } - ], - "has_more": True, + }, + "address": { + "address_zip": "0185128", + "city": "Nowhereville", + "country": "US", + "state": "Alaska" + }, + "mrr": 3000.0, + "arr": 36000.0, + "billing-system-url": "https:\/\/dashboard.stripe.com\/customers\/cus_4Z2ZpyJFuQ0XMb", + "chartmogul-url": "https:\/\/app.chartmogul.com\/#customers\/25647-Example_Company", + "billing-system-type": "Stripe", + "currency": "USD", + "currency-sign": "$" +} + +allContactsOld = { + "entries": [entry], "per_page": 50, "page": 1, "current_page": 1, - "total_pages": 4 + "total_pages": 4, +} + +allContactsNew = { + "entries": [entry], + "cursor": "cursor==", + "has_more": True } deserializedCustomer = Customer( @@ -321,26 +326,19 @@ ] } -allContacts = { - "entries": [contact], - "cursor": "MjAyMy0wMy0xMFQwMzo1MzoxNS44MTg1MjUwMDArMDA6MDAmY29uXzE2NDcwZjk4LWJlZjctMTFlZC05MjA4LTdiMDhhNDBmMzA0OQ==", - "has_more": False -} - class CustomerTestCase(unittest.TestCase): """ Tests complex nested structure & assymetric create/retrieve schema. """ - @requests_mock.mock() - def test_all(self, mock_requests): + def test_all_old_pagination(self, mock_requests): mock_requests.register_uri( 'GET', "https://api.chartmogul.com/v1/customers", request_headers={'Authorization': 'Basic dG9rZW46'}, status_code=200, - json=docsListSample + json=allContactsOld ) config = Config("token") @@ -348,7 +346,6 @@ def test_all(self, mock_requests): expected = Customer._many( entries=[deserializedCustomer], - has_more=True, per_page=50, page=1, current_page=1, @@ -368,13 +365,45 @@ def test_all(self, mock_requests): self.assertEqual(sorted(customers.entries[0].attributes.clearbit), sorted(expected.entries[0].attributes.clearbit)) self.assertTrue(isinstance(customers.entries[0], Customer)) + @requests_mock.mock() + def test_all_new_pagination(self, mock_requests): + mock_requests.register_uri( + 'GET', + "https://api.chartmogul.com/v1/customers", + request_headers={'Authorization': 'Basic dG9rZW46'}, + status_code=200, + json=allContactsNew + ) + + config = Config("token") + customers = Customer.all(config).get() + + expected = Customer._many( + entries=[deserializedCustomer], + has_more=True, + cursor="cursor==" + ) + + self.assertEqual(mock_requests.call_count, 1, "expected call") + self.assertEqual(mock_requests.last_request.qs, {}) + self.assertEqual(mock_requests.last_request.text, None) + # Complete comparing too complicated, would need to: + # 1) sort all dictionaries, + # 2) use special class/library for timezones (Python has no default) + # self.assertEqual(str(customers), str(expected)) + # => check only first level fields are OK + self.assertEqual(sorted(dir(customers)), sorted(dir(expected))) + self.assertEqual(sorted(customers.entries[0].attributes.stripe), sorted(expected.entries[0].attributes.stripe)) + self.assertEqual(sorted(customers.entries[0].attributes.clearbit), sorted(expected.entries[0].attributes.clearbit)) + self.assertTrue(isinstance(customers.entries[0], Customer)) + @requests_mock.mock() def test_create(self, mock_requests): mock_requests.register_uri( 'POST', "https://api.chartmogul.com/v1/customers", status_code=200, - json=docsListSample["entries"][0] + json=entry ) config = Config("token") @@ -384,12 +413,12 @@ def test_create(self, mock_requests): self.assertEqual(mock_requests.last_request.json(), sentCreateExpected) @requests_mock.mock() - def test_search(self, mock_requests): + def test_search_old_pagination(self, mock_requests): mock_requests.register_uri( 'GET', "https://api.chartmogul.com/v1/customers/search?email=tralala@someemail.com", status_code=200, - json=docsListSample + json=allContactsOld ) config = Config("token") @@ -400,6 +429,28 @@ def test_search(self, mock_requests): self.assertEqual(mock_requests.last_request.text, None) self.assertTrue(isinstance(result, Customer._many)) self.assertTrue(isinstance(result.entries[0], Customer)) + self.assertEqual(result.current_page, 1) + self.assertEqual(result.total_pages, 4) + + @requests_mock.mock() + def test_search_new_pagination(self, mock_requests): + mock_requests.register_uri( + 'GET', + "https://api.chartmogul.com/v1/customers/search?email=tralala@someemail.com", + status_code=200, + json=allContactsNew + ) + + config = Config("token") + result = Customer.search(config, email='tralala@someemail.com').get() + self.assertEqual(mock_requests.call_count, 1, "expected call") + self.assertEqual(mock_requests.last_request.qs, { + 'email': ['tralala@someemail.com']}) + self.assertEqual(mock_requests.last_request.text, None) + self.assertTrue(isinstance(result, Customer._many)) + self.assertTrue(isinstance(result.entries[0], Customer)) + self.assertTrue(result.has_more) + self.assertEqual(result.cursor, "cursor==") @requests_mock.mock() def test_merge(self, mock_requests): @@ -420,6 +471,7 @@ def test_merge(self, mock_requests): self.assertEqual(mock_requests.last_request.qs, {}) self.assertEqual(mock_requests.last_request.json(), jsonRequest) self.assertEqual(result, None) + @requests_mock.mock() def test_connectSubscriptions(self, mock_requests): mock_requests.register_uri( @@ -496,18 +548,20 @@ def test_contacts(self, mock_requests): "GET", "https://api.chartmogul.com/v1/customers/cus_00000000-0000-0000-0000-000000000000/contacts", status_code=200, - json=allContacts + json=allContactsNew ) config = Config("token") contacts = Customer.contacts(config, uuid="cus_00000000-0000-0000-0000-000000000000").get() - expected = Contact._many(**allContacts) + expected = Contact._many(**allContactsNew) self.assertEqual(mock_requests.call_count, 1, "expected call") self.assertEqual(mock_requests.last_request.qs, {}) self.assertEqual(mock_requests.last_request.text, None) self.assertEqual(sorted(dir(contacts)), sorted(dir(expected))) self.assertTrue(isinstance(contacts.entries[0], Contact)) + self.assertEqual(contacts.cursor, "cursor==") + self.assertTrue(contacts.has_more) @requests_mock.mock() def test_createContact(self, mock_requests): diff --git a/test/api/test_customers/test_activity.py b/test/api/test_customers/test_activity.py index 86deac8..329386d 100644 --- a/test/api/test_customers/test_activity.py +++ b/test/api/test_customers/test_activity.py @@ -34,7 +34,8 @@ def test_all(self, mock_requests): ], "has_more":False, "per_page":200, - "page":1 + "page":1, + "cursor": "cursor==" } ) config = Config("token") # is actually checked in mock @@ -44,3 +45,5 @@ def test_all(self, mock_requests): self.assertEqual(mock_requests.last_request.qs, {}) self.assertEqual(result.__class__.__name__, CustomerActivity._many.__name__) self.assertEqual(result.entries[0].id, 48730) + self.assertEqual(result.cursor, "cursor==") + self.assertFalse(result.has_more) diff --git a/test/api/test_customers/test_subscription.py b/test/api/test_customers/test_subscription.py index ccd42cc..fda61ba 100644 --- a/test/api/test_customers/test_subscription.py +++ b/test/api/test_customers/test_subscription.py @@ -100,8 +100,8 @@ def test_list_imported_subscriptions(self, mock_requests): "cancellation_dates":[] } ], - "current_page": 1, - "total_pages": 1 + "cursor": "cursor==", + "has_more": False } ) config = Config("token") # is actually checked in mock @@ -141,7 +141,8 @@ def test_all(self, mock_requests): ], "has_more": False, "per_page": 200, - "page": 1 + "page": 1, + "cursor": "cursor==" } ) config = Config("token") # is actually checked in mock @@ -151,3 +152,5 @@ def test_all(self, mock_requests): self.assertEqual(mock_requests.last_request.qs, {}) self.assertEqual(result.__class__.__name__, CustomerSubscription._many.__name__) self.assertEqual(result.entries[0].external_id, "sub_0001") + self.assertEqual(result.page, 1) + self.assertEqual(result.cursor, "cursor==") diff --git a/test/api/test_invoice.py b/test/api/test_invoice.py index 2608692..88ce5a5 100644 --- a/test/api/test_invoice.py +++ b/test/api/test_invoice.py @@ -166,9 +166,8 @@ ] } -newInvoiceListExample = """ -{ - "invoices": [ +oldInvoiceListExample = { + "invoices": [ { "uuid": "inv_565c73b2-85b9-49c9-a25e-2b7df6a677c9", "customer_uuid": "cus_f466e33d-ff2b-4a11-8f85-417eb02157a7", @@ -179,11 +178,11 @@ "line_items": [ { "uuid": "li_d72e6843-5793-41d0-bfdf-0269514c9c56", - "external_id": null, + "external_id": None, "type": "subscription", "subscription_uuid": "sub_e6bc5407-e258-4de0-bb43-61faaf062035", "plan_uuid": "pl_eed05d54-75b4-431b-adb2-eb6b9e543206", - "prorated": false, + "prorated": False, "service_period_start": "2015-11-01T00:00:00.000Z", "service_period_end": "2015-12-01T00:00:00.000Z", "amount_in_cents": 5000, @@ -191,11 +190,11 @@ "discount_code": "PSO86", "discount_amount_in_cents": 1000, "tax_amount_in_cents": 900, - "account_code": null + "account_code": None }, { "uuid": "li_0cc8c112-beac-416d-af11-f35744ca4e83", - "external_id": null, + "external_id": None, "type": "one_time", "description": "Setup Fees", "amount_in_cents": 2500, @@ -203,7 +202,7 @@ "discount_code": "PSO86", "discount_amount_in_cents": 500, "tax_amount_in_cents": 450, - "account_code": null, + "account_code": None, "discount_description": "Special 20 % discount", "transaction_fees_in_cents": 50, "transaction_fees_currency": "CZK", @@ -213,71 +212,129 @@ "transactions": [ { "uuid": "tr_879d560a-1bec-41bb-986e-665e38a2f7bc", - "external_id": null, + "external_id": None, "type": "payment", "date": "2015-11-05T00:14:23.000Z", "result": "successful" } ] } - ], - "current_page": 1, - "total_pages": 1 + ], + "current_page": 1, + "total_pages": 1 } -""" - -retrieveInvoiceExample = """ -{ - "uuid": "inv_22910fc6-c931-48e7-ac12-90d2cb5f0059", - "external_id": "INV0001", - "date": "2015-11-01T00:00:00.000Z", - "due_date": "2015-11-15T00:00:00.000Z", - "currency": "USD", - "line_items": [ - { - "uuid": "li_d72e6843-5793-41d0-bfdf-0269514c9c56", - "external_id": null, - "type": "subscription", - "subscription_uuid": "sub_e6bc5407-e258-4de0-bb43-61faaf062035", - "plan_uuid": "pl_eed05d54-75b4-431b-adb2-eb6b9e543206", - "prorated": false, - "service_period_start": "2015-11-01T00:00:00.000Z", - "service_period_end": "2015-12-01T00:00:00.000Z", - "amount_in_cents": 5000, - "quantity": 1, - "discount_code": "PSO86", - "discount_amount_in_cents": 1000, - "tax_amount_in_cents": 900, - "account_code": null - }, - { - "uuid": "li_0cc8c112-beac-416d-af11-f35744ca4e83", - "external_id": null, - "type": "one_time", - "description": "Setup Fees", - "amount_in_cents": 2500, - "quantity": 1, - "discount_code": "PSO86", - "discount_amount_in_cents": 500, - "tax_amount_in_cents": 450, - "account_code": null, - "discount_description": "Special 20 % discount", - "transaction_fees_in_cents": 50, - "transaction_fees_currency": "CZK", - "event_order": 5 - } - ], - "transactions": [ + + +newInvoiceListExample = { + "invoices": [ { - "uuid": "tr_879d560a-1bec-41bb-986e-665e38a2f7bc", - "external_id": null, - "type": "payment", - "date": "2015-11-05T00:14:23.000Z", - "result": "successful" + "uuid": "inv_565c73b2-85b9-49c9-a25e-2b7df6a677c9", + "customer_uuid": "cus_f466e33d-ff2b-4a11-8f85-417eb02157a7", + "external_id": "INV0001", + "date": "2015-11-01T00:00:00.000Z", + "due_date": "2015-11-15T00:00:00.000Z", + "currency": "USD", + "line_items": [ + { + "uuid": "li_d72e6843-5793-41d0-bfdf-0269514c9c56", + "external_id": None, + "type": "subscription", + "subscription_uuid": "sub_e6bc5407-e258-4de0-bb43-61faaf062035", + "plan_uuid": "pl_eed05d54-75b4-431b-adb2-eb6b9e543206", + "prorated": False, + "service_period_start": "2015-11-01T00:00:00.000Z", + "service_period_end": "2015-12-01T00:00:00.000Z", + "amount_in_cents": 5000, + "quantity": 1, + "discount_code": "PSO86", + "discount_amount_in_cents": 1000, + "tax_amount_in_cents": 900, + "account_code": None + }, + { + "uuid": "li_0cc8c112-beac-416d-af11-f35744ca4e83", + "external_id": None, + "type": "one_time", + "description": "Setup Fees", + "amount_in_cents": 2500, + "quantity": 1, + "discount_code": "PSO86", + "discount_amount_in_cents": 500, + "tax_amount_in_cents": 450, + "account_code": None, + "discount_description": "Special 20 % discount", + "transaction_fees_in_cents": 50, + "transaction_fees_currency": "CZK", + "event_order": 5 + } + ], + "transactions": [ + { + "uuid": "tr_879d560a-1bec-41bb-986e-665e38a2f7bc", + "external_id": None, + "type": "payment", + "date": "2015-11-05T00:14:23.000Z", + "result": "successful" + } + ] } - ] + ], + "cursor": "cursor==", + "has_more": False } -""" + + +retrieveInvoiceExample = { + "uuid": "inv_22910fc6-c931-48e7-ac12-90d2cb5f0059", + "external_id": "INV0001", + "date": "2015-11-01T00:00:00.000Z", + "due_date": "2015-11-15T00:00:00.000Z", + "currency": "USD", + "line_items": [ + { + "uuid": "li_d72e6843-5793-41d0-bfdf-0269514c9c56", + "external_id": None, + "type": "subscription", + "subscription_uuid": "sub_e6bc5407-e258-4de0-bb43-61faaf062035", + "plan_uuid": "pl_eed05d54-75b4-431b-adb2-eb6b9e543206", + "prorated": False, + "service_period_start": "2015-11-01T00:00:00.000Z", + "service_period_end": "2015-12-01T00:00:00.000Z", + "amount_in_cents": 5000, + "quantity": 1, + "discount_code": "PSO86", + "discount_amount_in_cents": 1000, + "tax_amount_in_cents": 900, + "account_code": None + }, + { + "uuid": "li_0cc8c112-beac-416d-af11-f35744ca4e83", + "external_id": None, + "type": "one_time", + "description": "Setup Fees", + "amount_in_cents": 2500, + "quantity": 1, + "discount_code": "PSO86", + "discount_amount_in_cents": 500, + "tax_amount_in_cents": 450, + "account_code": None, + "discount_description": "Special 20 % discount", + "transaction_fees_in_cents": 50, + "transaction_fees_currency": "CZK", + "event_order": 5 + } + ], + "transactions": [ + { + "uuid": "tr_879d560a-1bec-41bb-986e-665e38a2f7bc", + "external_id": None, + "type": "payment", + "date": "2015-11-05T00:14:23.000Z", + "result": "successful" + } + ] +} + class InvoiceTestCase(unittest.TestCase): """ @@ -308,6 +365,8 @@ def test_create(self, mock_requests): @requests_mock.mock() def test_list_has_customer_uuid(self, mock_requests): responseData['customer_uuid'] = 'UUID' + responseData['total_pages'] = 1 + responseData['current_page'] = 1 mock_requests.register_uri( 'GET', @@ -327,11 +386,12 @@ def test_list_has_customer_uuid(self, mock_requests): self.assertEqual(len(result.invoices), 1) self.assertTrue(isinstance(result.invoices[0], Invoice)) self.assertEqual(result.invoices[0].uuid, "inv_565c73b2-85b9-49c9-a25e-2b7df6a677c9") - self.assertEqual(result.customer_uuid, 'UUID') + self.assertEqual(result.customer_uuid, "UUID") + self.assertEqual(result.total_pages, 1) + self.assertEqual(result.current_page, 1) @requests_mock.mock() - def test_new_list(self, mock_requests): - + def test_new_list_old_pagination(self, mock_requests): mock_requests.register_uri( 'GET', ("https://api.chartmogul.com/v1/invoices" @@ -339,7 +399,7 @@ def test_new_list(self, mock_requests): request_headers={'Authorization': 'Basic dG9rZW46'}, headers={'Content-Type': 'application/json'}, status_code=200, - text=newInvoiceListExample + json=oldInvoiceListExample ) config = Config("token") # is actually checked in mock @@ -362,8 +422,38 @@ def test_new_list(self, mock_requests): self.assertEqual(result.total_pages, 1) @requests_mock.mock() - def test_delete(self, mock_requests): + def test_new_list_new_pagination(self, mock_requests): + mock_requests.register_uri( + 'GET', + ("https://api.chartmogul.com/v1/invoices" + "?external_id=INV0001&customer_uuid=cus_f466e33d-ff2b-4a11-8f85-417eb02157a7"), + request_headers={'Authorization': 'Basic dG9rZW46'}, + headers={'Content-Type': 'application/json'}, + status_code=200, + json=newInvoiceListExample + ) + + config = Config("token") # is actually checked in mock + result = Invoice.all(config, + customer_uuid='cus_f466e33d-ff2b-4a11-8f85-417eb02157a7', + external_id='INV0001').get() + + self.assertEqual(mock_requests.call_count, 1, "expected call") + cu = [] + cu.append('cus_f466e33d-ff2b-4a11-8f85-417eb02157a7') + ei = [] + ei.append('inv0001') + self.assertEqual(mock_requests.last_request.qs, {'customer_uuid': cu,'external_id': ei}) + # Struct too complex to do 1:1 comparison + self.assertTrue(isinstance(result, Invoice._many)) + self.assertEqual(len(result.invoices), 1) + + self.assertEqual(result.invoices[0].customer_uuid, 'cus_f466e33d-ff2b-4a11-8f85-417eb02157a7') + self.assertFalse(result.has_more) + self.assertEqual(result.cursor, "cursor==") + @requests_mock.mock() + def test_delete(self, mock_requests): mock_requests.register_uri( 'DELETE', ("https://api.chartmogul.com/v1/invoices" @@ -382,7 +472,6 @@ def test_delete(self, mock_requests): @requests_mock.mock() def test_delete_not_found(self, mock_requests): - mock_requests.register_uri( 'DELETE', ("https://api.chartmogul.com/v1/invoices" @@ -422,14 +511,13 @@ def test_delete_all(self, mock_requests): @requests_mock.mock() def test_retrieve_invoice(self, mock_requests): - mock_requests.register_uri( 'GET', ("https://api.chartmogul.com/v1/invoices/inv_22910fc6-c931-48e7-ac12-90d2cb5f0059"), request_headers={'Authorization': 'Basic dG9rZW46'}, headers={'Content-Type': 'application/json'}, status_code=200, - text=retrieveInvoiceExample + json=retrieveInvoiceExample ) config = Config("token") # is actually checked in mock diff --git a/test/api/test_plan.py b/test/api/test_plan.py index 84435a1..d940ec5 100644 --- a/test/api/test_plan.py +++ b/test/api/test_plan.py @@ -12,7 +12,7 @@ class PlanTestCase(unittest.TestCase): maxDiff = None @requests_mock.mock() - def test_cursor_list_plans(self, mock_requests): + def test_cursor_list_plans_old_pagination(self, mock_requests): expected_plan_dict = {"uuid": u"whatever_uuid", "data_source_uuid": u"some_uuid", "name": u"some plan", @@ -33,8 +33,10 @@ def test_cursor_list_plans(self, mock_requests): plan = Plan.all(config, page=5, per_page=12, data_source_uuid="some_uuid", external_id="custom_filter").get() - expected = Plan._many([Plan(**expected_plan_dict)], - current_page=5, total_pages=18) + expected = Plan._many( + [Plan(**expected_plan_dict)], + current_page=5, total_pages=18 + ) self.assertEqual(mock_requests.call_count, 1, "expected call") self.assertEqual(mock_requests.last_request.qs, { 'data_source_uuid': ['some_uuid'], @@ -45,6 +47,31 @@ def test_cursor_list_plans(self, mock_requests): self.assertEqual(mock_requests.last_request.text, None) self.assertEqual(str(plan), str(expected)) + @requests_mock.mock() + def test_cursor_list_plans_new_pagination(self, mock_requests): + expected_plan_dict = {"uuid": u"whatever_uuid", + "data_source_uuid": u"some_uuid", + "name": u"some plan", + "interval_count": 2, + "interval_unit": u"moonshines", + "external_id": u"custom_filter"} + mock_requests.register_uri( + 'GET', + ("https://api.chartmogul.com/v1/plans?cursor=cursor==" + "&per_page=12&data_source_uuid=some_uuid&external_id=custom_filter"), + request_headers={'Authorization': 'Basic dG9rZW46'}, + status_code=200, + json={"plans": [expected_plan_dict], + "has_more": True, + "cursor": "cursor=="} + ) + config = Config("token") # is actually checked in mock + plan = Plan.all(config, cursor="cursor==", per_page=12, + data_source_uuid="some_uuid", + external_id="custom_filter").get() + expected = Plan._many([Plan(**expected_plan_dict)], has_more=True, cursor="cursor==") + self.assertEqual(str(plan), str(expected)) + @requests_mock.mock() def test_modify_plan(self, mock_requests): expected_plan_dict = { diff --git a/test/api/test_plan_group.py b/test/api/test_plan_group.py index fe20515..b2b4935 100644 --- a/test/api/test_plan_group.py +++ b/test/api/test_plan_group.py @@ -65,7 +65,7 @@ def test_retrieve_plan_group(self, mock_requests): self.assertEqual(result.plans_count, 2) @requests_mock.mock() - def test_retrieve_plan_group_plans(self, mock_requests): + def test_retrieve_plan_group_plans_old_pagination(self, mock_requests): expected_plans = { "plans": [ { @@ -104,9 +104,54 @@ def test_retrieve_plan_group_plans(self, mock_requests): self.assertEqual(result.plans[0].uuid, "pl_cef31082-37be-11ea-a7bc-cb55fa0afcbb") self.assertEqual(result.plans[1].uuid, "pl_cef46630-37be-11ea-a7bc-a316cc9407e9") self.assertEqual(len(result.plans), 2) + self.assertEqual(result.total_pages, 1) + self.assertEqual(result.current_page, 1) @requests_mock.mock() - def test_all_plan_groups(self, mock_requests): + def test_retrieve_plan_group_plans_new_pagination(self, mock_requests): + expected_plans = { + "plans": [ + { + "name": "Berghain Flatrate Pack - bi-annual", + "uuid": "pl_cef31082-37be-11ea-a7bc-cb55fa0afcbb", + "data_source_uuid": "ds_73c24b7e-37be-11ea-85a4-03a4322daccc", + "interval_count": 6, + "interval_unit": "month", + "external_id": "plan_EOwj9vInDKILy1" + }, + { + "name": "Berghain Flatrate Pack - Skip the Queue Pack", + "uuid": "pl_cef46630-37be-11ea-a7bc-a316cc9407e9", + "data_source_uuid": "ds_73c24b7e-37be-11ea-85a4-03a4322daccc", + "interval_count": 1, + "interval_unit": "month", + "external_id": "plan_EOsEG3pyySMBEP" + } + ], + "has_more": False, + "cursor": "cursor==" + } + mock_requests.register_uri( + 'GET', + "https://api.chartmogul.com/v1/plan_groups/whatever_uuid/plans", + request_headers={'Authorization': 'Basic dG9rZW46'}, + status_code=200, + json=expected_plans + ) + + config = Config("token") # is actually checked in mock + result = PlanGroup.all(config, uuid="whatever_uuid").get() + + self.assertEqual(mock_requests.call_count, 1, "expected call") + self.assertEqual(mock_requests.last_request.qs, {}) + self.assertEqual(result.plans[0].uuid, "pl_cef31082-37be-11ea-a7bc-cb55fa0afcbb") + self.assertEqual(result.plans[1].uuid, "pl_cef46630-37be-11ea-a7bc-a316cc9407e9") + self.assertEqual(len(result.plans), 2) + self.assertEqual(result.cursor, "cursor==") + self.assertFalse(result.has_more) + + @requests_mock.mock() + def test_all_plan_groups_old_pagination(self, mock_requests): expected_plan_groups = { "plan_groups": [ { @@ -139,6 +184,45 @@ def test_all_plan_groups(self, mock_requests): self.assertTrue(isinstance(result.plan_groups[0], PlanGroup)) self.assertEqual(result.plan_groups[0].uuid, "whatever_uuid") self.assertEqual(result.plan_groups[1].uuid, "my_uuid") + self.assertEqual(result.total_pages, 1) + self.assertEqual(result.current_page, 1) + + @requests_mock.mock() + def test_all_plan_groups_new_pagination(self, mock_requests): + expected_plan_groups = { + "plan_groups": [ + { + "uuid": u"whatever_uuid", + "name": u"good_plan", + "plans_count": 2 + }, + { + "uuid": u"my_uuid", + "name": u"best_plan", + "plans_count": 5 + }, + ], + "has_more": False, + "cursor": "cursor==" + } + mock_requests.register_uri( + 'GET', + "https://api.chartmogul.com/v1/plan_groups", + status_code=200, + json=expected_plan_groups + ) + + config = Config("token") + result = PlanGroup.all(config).get() + + self.assertEqual(mock_requests.call_count, 1, "expected call") + self.assertEqual(mock_requests.last_request.qs, {}) + self.assertEqual(mock_requests.last_request.text, None) + self.assertTrue(isinstance(result.plan_groups[0], PlanGroup)) + self.assertEqual(result.plan_groups[0].uuid, "whatever_uuid") + self.assertEqual(result.plan_groups[1].uuid, "my_uuid") + self.assertFalse(result.has_more) + self.assertEqual(result.cursor, "cursor==") @requests_mock.mock() def test_destroy_plan_group(self, mock_requests): diff --git a/test/api/test_subscription.py b/test/api/test_subscription.py index d04524f..6f51e0d 100644 --- a/test/api/test_subscription.py +++ b/test/api/test_subscription.py @@ -10,7 +10,6 @@ class SubscriptionsTestCase(unittest.TestCase): """ Tests cancel, because it has custom path. """ - @requests_mock.mock() def test_cancel_subscription(self, mock_requests): """ Test cancel (patch) subscription (cancelled_at). @@ -100,8 +99,8 @@ def test_list_imported_subscriptions(self, mock_requests): "cancellation_dates":[] } ], - "current_page": 1, - "total_pages": 1 + "has_more": False, + "cursor": "cursor==" } ) config = Config("token") # is actually checked in mock @@ -111,3 +110,5 @@ def test_list_imported_subscriptions(self, mock_requests): self.assertEqual(mock_requests.last_request.qs, {}) self.assertEqual(result.__class__.__name__, Subscription._many.__name__) self.assertEqual(result.customer_uuid, "some_uuid") + self.assertEqual(result.cursor, "cursor==") + self.assertFalse(result.has_more) diff --git a/test/api/test_subscription_event.py b/test/api/test_subscription_event.py index 9fc80c1..b8eef9c 100644 --- a/test/api/test_subscription_event.py +++ b/test/api/test_subscription_event.py @@ -10,44 +10,64 @@ from chartmogul import ArgumentMissingError expected_sub_ev = { - "id": 7654321, - "external_id": "evnt_026", - "customer_external_id": "scus_022", - "data_source_uuid": "ds_1fm3eaac-62d0-31ec-clf4-4bf0mbe81aba", - "event_type": "subscription_start_scheduled", - "event_date": "2022-03-30 23:00:00.000", - "effective_date": "2022-04-01 23:00:00.000", - "subscription_external_id": "sub_0001", - "plan_external_id": "gol d_monthly", - "currency": "USD", - "amount_in_cents": 1000 + "id": 7654321, + "external_id": "evnt_026", + "customer_external_id": "scus_022", + "data_source_uuid": "ds_1fm3eaac-62d0-31ec-clf4-4bf0mbe81aba", + "event_type": "subscription_start_scheduled", + "event_date": "2022-03-30 23:00:00.000", + "effective_date": "2022-04-01 23:00:00.000", + "subscription_external_id": "sub_0001", + "plan_external_id": "gol d_monthly", + "currency": "USD", + "amount_in_cents": 1000 } -sub_ev_list_expected = { +sub_ev_list_expected_old = { "subscription_events": [ - { - "id": 7654321, - "external_id": "evnt_026", - "customer_external_id": "scus_022", - "data_source_uuid": "ds_1fm3eaac-62d0-31ec-clf4-4bf0mbe81aba", - "event_type": "subscription_start_scheduled", - "event_date": "2022-03-30 23:00:00.000", - "effective_date": "2022-04-01 23:00:00.000", - "subscription_external_id": "sub_0001", - "plan_external_id": "gol d_monthly", - "currency": "USD", - "amount_in_cents": 1000 - } + { + "id": 7654321, + "external_id": "evnt_026", + "customer_external_id": "scus_022", + "data_source_uuid": "ds_1fm3eaac-62d0-31ec-clf4-4bf0mbe81aba", + "event_type": "subscription_start_scheduled", + "event_date": "2022-03-30 23:00:00.000", + "effective_date": "2022-04-01 23:00:00.000", + "subscription_external_id": "sub_0001", + "plan_external_id": "gol d_monthly", + "currency": "USD", + "amount_in_cents": 1000 + } ], "meta": { "next_key": 67048503, "prev_key": None, "before_key": "2022-04-10T22:27:35.834Z", - "page": 1, + "page": 1, "total_pages": 166 } } +sub_ev_list_expected_new = { + "subscription_events": [ + { + "id": 7654321, + "external_id": "evnt_026", + "customer_external_id": "scus_022", + "data_source_uuid": "ds_1fm3eaac-62d0-31ec-clf4-4bf0mbe81aba", + "event_type": "subscription_start_scheduled", + "event_date": "2022-03-30 23:00:00.000", + "effective_date": "2022-04-01 23:00:00.000", + "subscription_external_id": "sub_0001", + "plan_external_id": "gol d_monthly", + "currency": "USD", + "amount_in_cents": 1000 + } + ], + "cursor": "cursor==", + "has_more": False +} + sub_ev_one = SubscriptionEvent( id=7654321, external_id="evnt_026", @@ -215,13 +235,13 @@ def test_modify_subscription_event_with_bad_params(self, mock_requests): self.fail('ArgumentMissingError not raised') @requests_mock.mock() - def test_all_subscription_events(self, mock_requests): + def test_all_subscription_events_old_pagination(self, mock_requests): mock_requests.register_uri( 'GET', "https://api.chartmogul.com/v1/subscription_events", request_headers={'Authorization': 'Basic dG9rZW46'}, status_code=200, - json=sub_ev_list_expected + json=sub_ev_list_expected_old ) config = Config("token") @@ -253,7 +273,7 @@ def test_all_subscription_events_with_filters(self, mock_requests): "&customer_external_id=scus_022&event_type=subscription_start_scheduled&plan_external_id=gol d_monthly", request_headers={'Authorization': 'Basic dG9rZW46'}, status_code=200, - json=sub_ev_list_expected + json=sub_ev_list_expected_new ) config = Config("token") @@ -264,13 +284,8 @@ def test_all_subscription_events_with_filters(self, mock_requests): expected = SubscriptionEvent._many( [SubscriptionEvent(**expected_sub_ev)], - meta={ - "next_key": 67048503, - "prev_key": None, - "before_key": "2022-04-10T22:27:35.834Z", - "page": 1, - "total_pages": 166 - } + has_more=True, + cursor="cursor==" ) self.assertEqual(mock_requests.call_count, 1, "expected call")