From e25888f2b8e2b0c6ae8f1e39c5d728bca4a3e927 Mon Sep 17 00:00:00 2001 From: Tyler Date: Tue, 21 Nov 2017 12:23:00 -0800 Subject: [PATCH 1/3] added entity_status and campaign tests --- tests/fixtures/campaigns_all.json | 9 ++++ tests/fixtures/campaigns_load.json | 1 + tests/test_campaign.py | 76 ++++++++++++++++++++++++++++++ twitter_ads/campaign.py | 1 + 4 files changed, 87 insertions(+) create mode 100644 tests/test_campaign.py diff --git a/tests/fixtures/campaigns_all.json b/tests/fixtures/campaigns_all.json index 85370d7..6e8e564 100644 --- a/tests/fixtures/campaigns_all.json +++ b/tests/fixtures/campaigns_all.json @@ -17,6 +17,7 @@ "total_budget_amount_local_micro": null, "id": "2wap7", "paused": false, + "entity_status": "ACTIVE", "account_id": "2iqph", "currency": "USD", "created_at": "2015-08-12T20:26:24Z", @@ -37,6 +38,7 @@ "total_budget_amount_local_micro": null, "id": "2wamv", "paused": true, + "entity_status": "PAUSED", "account_id": "2iqph", "currency": "USD", "created_at": "2015-08-12T20:17:39Z", @@ -58,6 +60,7 @@ "total_budget_amount_local_micro": null, "id": "2wai9", "paused": true, + "entity_status": "PAUSED", "account_id": "2iqph", "currency": "USD", "created_at": "2015-08-12T19:56:10Z", @@ -78,6 +81,7 @@ "total_budget_amount_local_micro": 1000000, "id": "2of1n", "paused": true, + "entity_status": "PAUSED", "account_id": "2iqph", "currency": "USD", "created_at": "2015-06-29T22:24:17Z", @@ -99,6 +103,7 @@ "total_budget_amount_local_micro": null, "id": "2w9n1", "paused": true, + "entity_status": "PAUSED", "account_id": "2iqph", "currency": "USD", "created_at": "2015-08-12T18:09:28Z", @@ -137,6 +142,7 @@ "total_budget_amount_local_micro": null, "id": "2vuj3", "paused": false, + "entity_status": "ACTIVE", "account_id": "2iqph", "currency": "USD", "created_at": "2015-08-10T21:06:04Z", @@ -155,6 +161,7 @@ "total_budget_amount_local_micro": 10000, "id": "2v3c4", "paused": false, + "entity_status": "ACTIVE", "account_id": "2iqph", "currency": "USD", "created_at": "2015-08-06T06:54:13Z", @@ -175,6 +182,7 @@ "total_budget_amount_local_micro": 100000000, "id": "2uubq", "paused": false, + "entity_status": "ACTIVE", "account_id": "2iqph", "currency": "USD", "created_at": "2015-08-04T23:20:11Z", @@ -195,6 +203,7 @@ "total_budget_amount_local_micro": null, "id": "2ttv3", "paused": true, + "entity_status": "PAUSED", "account_id": "2iqph", "currency": "USD", "created_at": "2015-07-29T23:05:56Z", diff --git a/tests/fixtures/campaigns_load.json b/tests/fixtures/campaigns_load.json index 47f868d..0771778 100644 --- a/tests/fixtures/campaigns_load.json +++ b/tests/fixtures/campaigns_load.json @@ -12,6 +12,7 @@ "total_budget_amount_local_micro": null, "id": "2wap7", "paused": false, + "entity_status": "ACTIVE", "account_id": "2iqph", "currency": "USD", "created_at": "2015-08-12T20:26:24Z", diff --git a/tests/test_campaign.py b/tests/test_campaign.py new file mode 100644 index 0000000..27b9fe1 --- /dev/null +++ b/tests/test_campaign.py @@ -0,0 +1,76 @@ +import pytest +import responses +import unittest + +from tests.support import with_resource, with_fixture, characters + +from twitter_ads.account import Account +from twitter_ads.campaign import Campaign +from twitter_ads.client import Client +from twitter_ads.cursor import Cursor +from twitter_ads import API_VERSION + + +class TestCampaigns(unittest.TestCase): + @responses.activate + def setUp(cls): + # Test account response + responses.add( + responses.GET, + with_resource('/' + API_VERSION + '/accounts/2iqph'), + body=with_fixture('accounts_load'), + content_type='application/json', + ) + + client = Client( + characters(40), + characters(40), + characters(40), + characters(40) + ) + + account = Account.load(client, '2iqph') + + # Set the client and account + cls.client = client + cls.account = account + + @responses.activate + def _get_all_campaigns(self): + # https://.../2/accounts/:account_id/campaigns + responses.add( + responses.GET, + with_resource('/' + API_VERSION + '/accounts/2iqph/campaigns'), + body=with_fixture('campaigns_all'), + content_type='application/json', + ) + + return self.account.campaigns() + + @responses.activate + def _get_campaign(self): + # https://.../2/accounts/:account_id/campaigns/:campaign_id + responses.add( + responses.GET, + with_resource( + '/' + API_VERSION + '/accounts/2iqph/campaigns/2wap7'), + body=with_fixture('campaigns_load'), + content_type='application/json', + ) + + return Campaign.load(self.account, '2wap7') + + def test_campaigns_all(self): + cursor = self._get_all_campaigns() + assert cursor is not None + assert isinstance(cursor, Cursor) + assert cursor.count == 10 + + def test_campaign_load(self): + campaign = self._get_campaign() + assert campaign + + def test_campaign_entity_status_exists(self): + campaign = self._get_campaign() + assert campaign.entity_status + assert campaign.entity_status == 'ACTIVE' diff --git a/twitter_ads/campaign.py b/twitter_ads/campaign.py index 46c1c97..216dddc 100644 --- a/twitter_ads/campaign.py +++ b/twitter_ads/campaign.py @@ -138,6 +138,7 @@ class Campaign(Resource, Persistence, Analytics, Batch): resource_property(Campaign, 'created_at', readonly=True, transform=TRANSFORM.TIME) resource_property(Campaign, 'updated_at', readonly=True, transform=TRANSFORM.TIME) resource_property(Campaign, 'deleted', readonly=True, transform=TRANSFORM.BOOL) +resource_property(Campaign, 'entity_status', readonly=True) # writable resource_property(Campaign, 'name') resource_property(Campaign, 'funding_instrument_id') From 02cbf6cb0c1d4a226861cd3ca25870b63b1597a8 Mon Sep 17 00:00:00 2001 From: Tyler Date: Tue, 21 Nov 2017 13:58:01 -0800 Subject: [PATCH 2/3] Fixed flake8 issues. Fixes #134. --- setup.py | 1 + tests/test_campaign.py | 157 ++++++++++++++++++++++++---------------- twitter_ads/account.py | 1 + twitter_ads/audience.py | 2 + twitter_ads/campaign.py | 7 ++ twitter_ads/creative.py | 14 ++++ twitter_ads/enum.py | 1 + twitter_ads/error.py | 1 + 8 files changed, 120 insertions(+), 64 deletions(-) diff --git a/setup.py b/setup.py index 5a9d7e0..9b9eb57 100644 --- a/setup.py +++ b/setup.py @@ -15,6 +15,7 @@ def get_version(version_tuple): return '.'.join(map(str, version_tuple[:-1])) + version_tuple[-1] return '.'.join(map(str, version_tuple)) + init = os.path.join(os.path.dirname(__file__), 'twitter_ads', '__init__.py') version_line = list(filter(lambda l: l.startswith('VERSION'), open(init)))[0] diff --git a/tests/test_campaign.py b/tests/test_campaign.py index 27b9fe1..6a5eb50 100644 --- a/tests/test_campaign.py +++ b/tests/test_campaign.py @@ -1,4 +1,3 @@ -import pytest import responses import unittest @@ -11,66 +10,96 @@ from twitter_ads import API_VERSION -class TestCampaigns(unittest.TestCase): - @responses.activate - def setUp(cls): - # Test account response - responses.add( - responses.GET, - with_resource('/' + API_VERSION + '/accounts/2iqph'), - body=with_fixture('accounts_load'), - content_type='application/json', - ) - - client = Client( - characters(40), - characters(40), - characters(40), - characters(40) - ) - - account = Account.load(client, '2iqph') - - # Set the client and account - cls.client = client - cls.account = account - - @responses.activate - def _get_all_campaigns(self): - # https://.../2/accounts/:account_id/campaigns - responses.add( - responses.GET, - with_resource('/' + API_VERSION + '/accounts/2iqph/campaigns'), - body=with_fixture('campaigns_all'), - content_type='application/json', - ) - - return self.account.campaigns() - - @responses.activate - def _get_campaign(self): - # https://.../2/accounts/:account_id/campaigns/:campaign_id - responses.add( - responses.GET, - with_resource( - '/' + API_VERSION + '/accounts/2iqph/campaigns/2wap7'), - body=with_fixture('campaigns_load'), - content_type='application/json', - ) - - return Campaign.load(self.account, '2wap7') - - def test_campaigns_all(self): - cursor = self._get_all_campaigns() - assert cursor is not None - assert isinstance(cursor, Cursor) - assert cursor.count == 10 - - def test_campaign_load(self): - campaign = self._get_campaign() - assert campaign - - def test_campaign_entity_status_exists(self): - campaign = self._get_campaign() - assert campaign.entity_status - assert campaign.entity_status == 'ACTIVE' +@responses.activate +def test_campaigns_all(): + responses.add( + responses.GET, + with_resource('/' + API_VERSION + '/accounts/2iqph'), + body=with_fixture('accounts_load'), + content_type='application/json', + ) + + responses.add( + responses.GET, + with_resource('/' + API_VERSION + '/accounts/2iqph/campaigns'), + body=with_fixture('campaigns_all'), + content_type='application/json', + ) + + client = Client( + characters(40), + characters(40), + characters(40), + characters(40) + ) + + account = Account.load(client, '2iqph') + + cursor = account.campaigns() + + assert cursor is not None + assert isinstance(cursor, Cursor) + assert cursor.count == 10 + + +@responses.activate +def test_campaign_load(): + responses.add( + responses.GET, + with_resource('/' + API_VERSION + '/accounts/2iqph'), + body=with_fixture('accounts_load'), + content_type='application/json', + ) + + responses.add( + responses.GET, + with_resource( + '/' + API_VERSION + '/accounts/2iqph/campaigns/2wap7'), + body=with_fixture('campaigns_load'), + content_type='application/json', + ) + + client = Client( + characters(40), + characters(40), + characters(40), + characters(40) + ) + + account = Account.load(client, '2iqph') + + campaign = Campaign.load(account, '2wap7') + + assert campaign + + +@responses.activate +def test_campaign_entity_status_exists(): + responses.add( + responses.GET, + with_resource('/' + API_VERSION + '/accounts/2iqph'), + body=with_fixture('accounts_load'), + content_type='application/json', + ) + + responses.add( + responses.GET, + with_resource( + '/' + API_VERSION + '/accounts/2iqph/campaigns/2wap7'), + body=with_fixture('campaigns_load'), + content_type='application/json', + ) + + client = Client( + characters(40), + characters(40), + characters(40), + characters(40) + ) + + account = Account.load(client, '2iqph') + + campaign = Campaign.load(account, '2wap7') + + assert campaign.entity_status + assert campaign.entity_status == 'ACTIVE' diff --git a/twitter_ads/account.py b/twitter_ads/account.py index 385f185..8821b2e 100644 --- a/twitter_ads/account.py +++ b/twitter_ads/account.py @@ -169,6 +169,7 @@ def scoped_timeline(self, *id, **kwargs): return response.body['data'] + # account properties resource_property(Account, 'id', readonly=True) resource_property(Account, 'name', readonly=True) diff --git a/twitter_ads/audience.py b/twitter_ads/audience.py index 3315939..efcc412 100644 --- a/twitter_ads/audience.py +++ b/twitter_ads/audience.py @@ -100,6 +100,7 @@ def __update_audience__(self, location, list_type, operation): resource = self.RESOURCE_UPDATE.format(account_id=self.account.id) return Request(self.account.client, 'post', resource, params=params).perform() + # tailored audience properties # read-only resource_property(TailoredAudience, 'id', readonly=True) @@ -171,6 +172,7 @@ def delete(self): response = Request(self.account.client, 'delete', resource).perform() return self.from_response(response.body['data']) + # tailored audience permission properties # read-only resource_property(TailoredAudiencePermission, 'id', readonly=True) diff --git a/twitter_ads/campaign.py b/twitter_ads/campaign.py index 216dddc..06f8e3f 100644 --- a/twitter_ads/campaign.py +++ b/twitter_ads/campaign.py @@ -29,6 +29,7 @@ def all(klass, account, line_item_id, **kwargs): return Cursor(klass, request, init_with=[account]) + # targeting criteria properties # read-only resource_property(TargetingCriteria, 'id', readonly=True) @@ -54,6 +55,7 @@ class FundingInstrument(Resource, Persistence): RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/funding_instruments' RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/funding_instruments/{id}' + # funding instrument properties # read-only resource_property(FundingInstrument, 'id', readonly=True) @@ -83,6 +85,7 @@ class PromotableUser(Resource): RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/promotable_users' RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/promotable_users/{id}' + # promotable user properties # read-only resource_property(PromotableUser, 'id', readonly=True) @@ -115,6 +118,7 @@ def apps(self): self.reload() return self._apps + # app list properties # read-only resource_property(AppList, 'id', readonly=True) @@ -130,6 +134,7 @@ class Campaign(Resource, Persistence, Analytics, Batch): RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/campaigns' RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/campaigns/{id}' + # campaign properties # read-only resource_property(Campaign, 'id', readonly=True) @@ -172,6 +177,7 @@ def targeting_criteria(self, id=None, **kwargs): else: return TargetingCriteria.load(self.account, id, **kwargs) + # line item properties # read-only resource_property(LineItem, 'id', readonly=True) @@ -207,6 +213,7 @@ class ScheduledPromotedTweet(Resource, Persistence): RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/scheduled_promoted_tweets' RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/scheduled_promoted_tweets/{id}' + # scheduled promoted tweets properties # read-only resource_property(ScheduledPromotedTweet, 'created_at', readonly=True, transform=TRANSFORM.TIME) diff --git a/twitter_ads/creative.py b/twitter_ads/creative.py index 8bc5129..609ebe4 100644 --- a/twitter_ads/creative.py +++ b/twitter_ads/creative.py @@ -17,6 +17,7 @@ class PromotedAccount(Resource, Persistence): RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/promoted_accounts' RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/promoted_accounts/{id}' + # promoted account properties # read-only resource_property(PromotedAccount, 'id', readonly=True) @@ -54,6 +55,7 @@ def save(self): response = Request(self.account.client, 'post', resource, params=params).perform() return self.from_response(response.body['data'][0]) + # promoted tweet properties # read-only resource_property(PromotedTweet, 'id', readonly=True) @@ -74,6 +76,7 @@ class Video(Resource, Persistence): RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/videos' RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/videos/{id}' + # video properties # read-only resource_property(Video, 'id', readonly=True) @@ -98,6 +101,7 @@ class AccountMedia(Resource, Persistence): RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/account_media' RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/account_media/{id}' + # video properties # read-only resource_property(AccountMedia, 'id', readonly=True) @@ -120,6 +124,7 @@ class MediaCreative(Resource, Persistence): RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/media_creatives' RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/media_creatives/{id}' + # video properties # read-only resource_property(MediaCreative, 'id', readonly=True) @@ -142,6 +147,7 @@ class WebsiteCard(Resource, Persistence): RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/cards/website' RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/cards/website/{id}' + # website card properties # read-only resource_property(WebsiteCard, 'id', readonly=True) @@ -164,6 +170,7 @@ class VideoWebsiteCard(Resource, Persistence): RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/cards/video_website' RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/cards/video_website/{id}' + # video website card properties # read-only resource_property(VideoWebsiteCard, 'account_id', readonly=True) @@ -199,6 +206,7 @@ class LeadGenCard(Resource, Persistence): RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/cards/lead_gen' RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/cards/lead_gen/{id}' + # lead gen card properties # read-only resource_property(LeadGenCard, 'id', readonly=True) @@ -229,6 +237,7 @@ class AppDownloadCard(Resource, Persistence): RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/cards/app_download' RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/cards/app_download/{id}' + # app download card properties # read-only resource_property(AppDownloadCard, 'id', readonly=True) @@ -257,6 +266,7 @@ class ImageAppDownloadCard(Resource, Persistence): RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/cards/image_app_download' RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/cards/image_app_download/{id}' + # image app download card properties # read-only resource_property(ImageAppDownloadCard, 'id', readonly=True) @@ -284,6 +294,7 @@ class VideoAppDownloadCard(Resource, Persistence): RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/cards/video_app_download' RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/cards/video_app_download/{id}' + # video app download card properties # read-only resource_property(VideoAppDownloadCard, 'id', readonly=True) @@ -314,6 +325,7 @@ class ImageConversationCard(Resource, Persistence): RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/cards/image_conversation' RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/cards/image_conversation/{id}' + # image conversation card properties # read-only resource_property(ImageConversationCard, 'id', readonly=True) @@ -340,6 +352,7 @@ class VideoConversationCard(Resource, Persistence): RESOURCE_COLLECTION = '/' + API_VERSION + '/accounts/{account_id}/cards/video_conversation' RESOURCE = '/' + API_VERSION + '/accounts/{account_id}/cards/video_conversation/{id}' + # video conversation card properties # read-only resource_property(VideoConversationCard, 'id', readonly=True) @@ -380,6 +393,7 @@ def preview(self): response = Request(self.account.client, 'get', resource).perform() return response.body['data'] + # scheduled tweet properties # read-only resource_property(ScheduledTweet, 'created_at', readonly=True, transform=TRANSFORM.TIME) diff --git a/twitter_ads/enum.py b/twitter_ads/enum.py index 3813281..5fdb88a 100644 --- a/twitter_ads/enum.py +++ b/twitter_ads/enum.py @@ -6,6 +6,7 @@ def enum(**enums): return type('Enum', (), enums) + TRANSFORM = enum( TIME=0, BOOL=1, diff --git a/twitter_ads/error.py b/twitter_ads/error.py index 2d95179..8d84205 100644 --- a/twitter_ads/error.py +++ b/twitter_ads/error.py @@ -99,6 +99,7 @@ def __init__(self, response, **kwargs): def retry_after(self): return self._retry_after + ERRORS = { 400: BadRequest, 401: NotAuthorized, From 6fd25ceeb53d4abb26fb23c47e3100c0ebcce192 Mon Sep 17 00:00:00 2001 From: Tyler Date: Mon, 27 Nov 2017 15:47:13 -0800 Subject: [PATCH 3/3] removed 'paused' from fixtures, added to line_items, added tests --- tests/fixtures/campaigns_all.json | 10 --- tests/fixtures/campaigns_load.json | 1 - tests/fixtures/line_items_all.json | 20 +++--- tests/fixtures/line_items_load.json | 2 +- tests/test_line_item.py | 105 ++++++++++++++++++++++++++++ twitter_ads/campaign.py | 5 +- 6 files changed, 118 insertions(+), 25 deletions(-) create mode 100644 tests/test_line_item.py diff --git a/tests/fixtures/campaigns_all.json b/tests/fixtures/campaigns_all.json index 6e8e564..80a63af 100644 --- a/tests/fixtures/campaigns_all.json +++ b/tests/fixtures/campaigns_all.json @@ -16,7 +16,6 @@ "standard_delivery": true, "total_budget_amount_local_micro": null, "id": "2wap7", - "paused": false, "entity_status": "ACTIVE", "account_id": "2iqph", "currency": "USD", @@ -37,7 +36,6 @@ "standard_delivery": true, "total_budget_amount_local_micro": null, "id": "2wamv", - "paused": true, "entity_status": "PAUSED", "account_id": "2iqph", "currency": "USD", @@ -59,7 +57,6 @@ "standard_delivery": true, "total_budget_amount_local_micro": null, "id": "2wai9", - "paused": true, "entity_status": "PAUSED", "account_id": "2iqph", "currency": "USD", @@ -80,7 +77,6 @@ "standard_delivery": true, "total_budget_amount_local_micro": 1000000, "id": "2of1n", - "paused": true, "entity_status": "PAUSED", "account_id": "2iqph", "currency": "USD", @@ -102,7 +98,6 @@ "standard_delivery": true, "total_budget_amount_local_micro": null, "id": "2w9n1", - "paused": true, "entity_status": "PAUSED", "account_id": "2iqph", "currency": "USD", @@ -123,7 +118,6 @@ "standard_delivery": true, "total_budget_amount_local_micro": 1000000, "id": "2vuug", - "paused": true, "account_id": "2iqph", "currency": "USD", "created_at": "2015-08-10T21:58:39Z", @@ -141,7 +135,6 @@ "standard_delivery": true, "total_budget_amount_local_micro": null, "id": "2vuj3", - "paused": false, "entity_status": "ACTIVE", "account_id": "2iqph", "currency": "USD", @@ -160,7 +153,6 @@ "standard_delivery": true, "total_budget_amount_local_micro": 10000, "id": "2v3c4", - "paused": false, "entity_status": "ACTIVE", "account_id": "2iqph", "currency": "USD", @@ -181,7 +173,6 @@ "standard_delivery": true, "total_budget_amount_local_micro": 100000000, "id": "2uubq", - "paused": false, "entity_status": "ACTIVE", "account_id": "2iqph", "currency": "USD", @@ -202,7 +193,6 @@ "standard_delivery": true, "total_budget_amount_local_micro": null, "id": "2ttv3", - "paused": true, "entity_status": "PAUSED", "account_id": "2iqph", "currency": "USD", diff --git a/tests/fixtures/campaigns_load.json b/tests/fixtures/campaigns_load.json index 0771778..09f3314 100644 --- a/tests/fixtures/campaigns_load.json +++ b/tests/fixtures/campaigns_load.json @@ -11,7 +11,6 @@ "standard_delivery": true, "total_budget_amount_local_micro": null, "id": "2wap7", - "paused": false, "entity_status": "ACTIVE", "account_id": "2iqph", "currency": "USD", diff --git a/tests/fixtures/line_items_all.json b/tests/fixtures/line_items_all.json index 110c9be..684afad 100644 --- a/tests/fixtures/line_items_all.json +++ b/tests/fixtures/line_items_all.json @@ -22,7 +22,7 @@ "total_budget_amount_local_micro": null, "objective": "CUSTOM", "id": "bw2", - "paused": false, + "entity_status": "ACTIVE", "account_id": "2iqph", "optimization": "DEFAULT", "categories": [], @@ -50,7 +50,7 @@ "total_budget_amount_local_micro": null, "objective": "CUSTOM", "id": "c4m", - "paused": false, + "entity_status": "ACTIVE", "account_id": "2iqph", "optimization": "DEFAULT", "categories": [], @@ -78,7 +78,7 @@ "total_budget_amount_local_micro": null, "objective": "CUSTOM", "id": "c5c", - "paused": false, + "entity_status": "ACTIVE", "account_id": "2iqph", "optimization": "DEFAULT", "categories": [], @@ -106,7 +106,7 @@ "total_budget_amount_local_micro": null, "objective": "CUSTOM", "id": "fhu", - "paused": false, + "entity_status": "ACTIVE", "account_id": "2iqph", "optimization": "DEFAULT", "categories": [], @@ -134,7 +134,7 @@ "total_budget_amount_local_micro": null, "objective": "CUSTOM", "id": "fxd", - "paused": false, + "entity_status": "ACTIVE", "account_id": "2iqph", "optimization": "DEFAULT", "categories": [], @@ -162,7 +162,7 @@ "total_budget_amount_local_micro": null, "objective": "CUSTOM", "id": "fxt", - "paused": false, + "entity_status": "ACTIVE", "account_id": "2iqph", "optimization": "DEFAULT", "categories": [], @@ -190,7 +190,7 @@ "total_budget_amount_local_micro": null, "objective": "CUSTOM", "id": "fya", - "paused": false, + "entity_status": "ACTIVE", "account_id": "2iqph", "optimization": "DEFAULT", "categories": [], @@ -218,7 +218,7 @@ "total_budget_amount_local_micro": null, "objective": "CUSTOM", "id": "ghj", - "paused": false, + "entity_status": "ACTIVE", "account_id": "2iqph", "optimization": "DEFAULT", "categories": [], @@ -246,7 +246,7 @@ "total_budget_amount_local_micro": null, "objective": "CUSTOM", "id": "gra", - "paused": false, + "entity_status": "ACTIVE", "account_id": "2iqph", "optimization": "DEFAULT", "categories": [], @@ -274,7 +274,7 @@ "total_budget_amount_local_micro": null, "objective": "CUSTOM", "id": "gsw", - "paused": false, + "entity_status": "ACTIVE", "account_id": "2iqph", "optimization": "DEFAULT", "categories": [], diff --git a/tests/fixtures/line_items_load.json b/tests/fixtures/line_items_load.json index 0dab002..a0dea6d 100644 --- a/tests/fixtures/line_items_load.json +++ b/tests/fixtures/line_items_load.json @@ -17,7 +17,7 @@ "total_budget_amount_local_micro": null, "objective": "CUSTOM", "id": "bw2", - "paused": false, + "entity_status": "ACTIVE", "account_id": "2iqph", "optimization": "DEFAULT", "categories": [], diff --git a/tests/test_line_item.py b/tests/test_line_item.py new file mode 100644 index 0000000..c67a78d --- /dev/null +++ b/tests/test_line_item.py @@ -0,0 +1,105 @@ +import responses +import unittest + +from tests.support import with_resource, with_fixture, characters + +from twitter_ads.account import Account +from twitter_ads.campaign import LineItem +from twitter_ads.client import Client +from twitter_ads.cursor import Cursor +from twitter_ads import API_VERSION + + +@responses.activate +def test_line_items_all(): + responses.add( + responses.GET, + with_resource('/' + API_VERSION + '/accounts/2iqph'), + body=with_fixture('accounts_load'), + content_type='application/json', + ) + + responses.add( + responses.GET, + with_resource('/' + API_VERSION + '/accounts/2iqph/line_items'), + body=with_fixture('line_items_all'), + content_type='application/json', + ) + + client = Client( + characters(40), + characters(40), + characters(40), + characters(40) + ) + + account = Account.load(client, '2iqph') + + cursor = account.line_items() + + assert cursor is not None + assert isinstance(cursor, Cursor) + assert cursor.count == 10 + + +@responses.activate +def test_line_item_load(): + responses.add( + responses.GET, + with_resource('/' + API_VERSION + '/accounts/2iqph'), + body=with_fixture('accounts_load'), + content_type='application/json', + ) + + responses.add( + responses.GET, + with_resource( + '/' + API_VERSION + '/accounts/2iqph/line_items/bw2'), + body=with_fixture('line_items_load'), + content_type='application/json', + ) + + client = Client( + characters(40), + characters(40), + characters(40), + characters(40) + ) + + account = Account.load(client, '2iqph') + + line_item = LineItem.load(account, 'bw2') + + assert line_item + + +@responses.activate +def test_line_item_entity_status_exists(): + responses.add( + responses.GET, + with_resource('/' + API_VERSION + '/accounts/2iqph'), + body=with_fixture('accounts_load'), + content_type='application/json', + ) + + responses.add( + responses.GET, + with_resource( + '/' + API_VERSION + '/accounts/2iqph/line_items/bw2'), + body=with_fixture('line_items_load'), + content_type='application/json', + ) + + client = Client( + characters(40), + characters(40), + characters(40), + characters(40) + ) + + account = Account.load(client, '2iqph') + + line_item = LineItem.load(account, 'bw2') + + assert line_item.entity_status + assert line_item.entity_status == 'ACTIVE' diff --git a/twitter_ads/campaign.py b/twitter_ads/campaign.py index 06f8e3f..b8a2faa 100644 --- a/twitter_ads/campaign.py +++ b/twitter_ads/campaign.py @@ -143,17 +143,16 @@ class Campaign(Resource, Persistence, Analytics, Batch): resource_property(Campaign, 'created_at', readonly=True, transform=TRANSFORM.TIME) resource_property(Campaign, 'updated_at', readonly=True, transform=TRANSFORM.TIME) resource_property(Campaign, 'deleted', readonly=True, transform=TRANSFORM.BOOL) -resource_property(Campaign, 'entity_status', readonly=True) # writable resource_property(Campaign, 'name') resource_property(Campaign, 'funding_instrument_id') resource_property(Campaign, 'start_time', transform=TRANSFORM.TIME) resource_property(Campaign, 'end_time', transform=TRANSFORM.TIME) -resource_property(Campaign, 'paused', transform=TRANSFORM.BOOL) resource_property(Campaign, 'currency') resource_property(Campaign, 'standard_delivery') resource_property(Campaign, 'daily_budget_amount_local_micro') resource_property(Campaign, 'total_budget_amount_local_micro') +resource_property(Campaign, 'entity_status') # sdk-only resource_property(Campaign, 'to_delete', transform=TRANSFORM.BOOL) @@ -193,7 +192,6 @@ def targeting_criteria(self, id=None, **kwargs): resource_property(LineItem, 'include_sentiment') resource_property(LineItem, 'objective') resource_property(LineItem, 'optimization') -resource_property(LineItem, 'paused', transform=TRANSFORM.BOOL) resource_property(LineItem, 'primary_web_event_tag') resource_property(LineItem, 'product_type') resource_property(LineItem, 'placements', transform=TRANSFORM.LIST) @@ -202,6 +200,7 @@ def targeting_criteria(self, id=None, **kwargs): resource_property(LineItem, 'bid_amount_local_micro') resource_property(LineItem, 'total_budget_amount_local_micro') resource_property(LineItem, 'bid_type') +resource_property(LineItem, 'entity_status') # sdk-only resource_property(LineItem, 'to_delete', transform=TRANSFORM.BOOL)