@@ -12,94 +12,56 @@

@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'),
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',
)
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)
)
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
campaign = cursor.next()
assert campaign.id == '2wap7'
assert campaign.entity_status == 'ACTIVE'


@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',
)
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',
)
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)
)
characters(40),
characters(40),
characters(40),
characters(40)
)

account = Account.load(client, '2iqph')

campaign = Campaign.load(account, '2wap7')

assert campaign.entity_status
assert campaign.id == '2wap7'
assert campaign.entity_status == 'ACTIVE'
@@ -12,94 +12,56 @@

@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'),
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',
)
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)
)
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
lineitem = cursor.next()
assert lineitem.id == 'bw2'
assert lineitem.entity_status == 'ACTIVE'


@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',
)
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',
)
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)
)
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.id == 'bw2'
assert line_item.entity_status == 'ACTIVE'
@@ -0,0 +1,67 @@
import responses
import unittest

from tests.support import with_resource, with_fixture, characters

from twitter_ads.account import Account
from twitter_ads.client import Client
from twitter_ads.creative import PromotedTweet
from twitter_ads.cursor import Cursor
from twitter_ads import API_VERSION


@responses.activate
def test_promoted_tweets_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/promoted_tweets'),
body=with_fixture('promoted_tweets_all'),
content_type='application/json')

client = Client(
characters(40),
characters(40),
characters(40),
characters(40)
)

account = Account.load(client, '2iqph')

cursor = PromotedTweet.all(account)
assert cursor is not None
assert isinstance(cursor, Cursor)
assert cursor.count == 20

promoted_tweet = cursor.next()
assert promoted_tweet.id == '6thl4'
assert promoted_tweet.entity_status == 'ACTIVE'


@responses.activate
def test_promoted_tweets_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/promoted_tweets/6thl4'),
body=with_fixture('promoted_tweets_load'),
content_type='application/json')

client = Client(
characters(40),
characters(40),
characters(40),
characters(40)
)

account = Account.load(client, '2iqph')

promoted_tweet = PromotedTweet.load(account, '6thl4')
assert promoted_tweet.id == '6thl4'
assert promoted_tweet.entity_status == 'ACTIVE'
@@ -137,22 +137,23 @@ class Campaign(Resource, Persistence, Analytics, Batch):

# campaign properties
# read-only
resource_property(Campaign, 'created_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(Campaign, 'deleted', readonly=True, transform=TRANSFORM.BOOL)
resource_property(Campaign, 'id', readonly=True)
resource_property(Campaign, 'reasons_not_servable', readonly=True)
resource_property(Campaign, 'servable', readonly=True, transform=TRANSFORM.BOOL)
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)
# writable
resource_property(Campaign, 'name')
resource_property(Campaign, 'daily_budget_amount_local_micro')
resource_property(Campaign, 'duration_in_days', transform=TRANSFORM.INT)
resource_property(Campaign, 'end_time', transform=TRANSFORM.TIME)
resource_property(Campaign, 'entity_status')
resource_property(Campaign, 'frequency_cap', transform=TRANSFORM.INT)
resource_property(Campaign, 'funding_instrument_id')
resource_property(Campaign, 'name')
resource_property(Campaign, 'standard_delivery', transform=TRANSFORM.BOOL)
resource_property(Campaign, 'start_time', transform=TRANSFORM.TIME)
resource_property(Campaign, 'end_time', transform=TRANSFORM.TIME)
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)

@@ -179,28 +180,33 @@ def targeting_criteria(self, id=None, **kwargs):

# line item properties
# read-only
resource_property(LineItem, 'id', readonly=True)
resource_property(LineItem, 'created_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(LineItem, 'updated_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(LineItem, 'deleted', readonly=True, transform=TRANSFORM.BOOL)
resource_property(LineItem, 'id', readonly=True)
resource_property(LineItem, 'updated_at', readonly=True, transform=TRANSFORM.TIME)
# writable
resource_property(LineItem, 'name')
resource_property(LineItem, 'campaign_id')
resource_property(LineItem, 'advertiser_domain')
resource_property(LineItem, 'advertiser_user_id')
resource_property(LineItem, 'automatically_select_bid', transform=TRANSFORM.BOOL)
resource_property(LineItem, 'bid_amount_local_micro')
resource_property(LineItem, 'bid_type')
resource_property(LineItem, 'bid_unit')
resource_property(LineItem, 'campaign_id')
resource_property(LineItem, 'categories', transform=TRANSFORM.LIST)
resource_property(LineItem, 'charge_by')
resource_property(LineItem, 'end_time', transform=TRANSFORM.TIME)
resource_property(LineItem, 'entity_status')
resource_property(LineItem, 'include_sentiment')
resource_property(LineItem, 'lookalike_expansion')
resource_property(LineItem, 'name')
resource_property(LineItem, 'objective')
resource_property(LineItem, 'optimization')
resource_property(LineItem, 'placements', transform=TRANSFORM.LIST)
resource_property(LineItem, 'primary_web_event_tag')
resource_property(LineItem, 'product_type')
resource_property(LineItem, 'placements', transform=TRANSFORM.LIST)
resource_property(LineItem, 'bid_unit')
resource_property(LineItem, 'automatically_select_bid', transform=TRANSFORM.BOOL)
resource_property(LineItem, 'bid_amount_local_micro')
resource_property(LineItem, 'start_time', transform=TRANSFORM.TIME)
resource_property(LineItem, 'total_budget_amount_local_micro')
resource_property(LineItem, 'bid_type')
resource_property(LineItem, 'entity_status')
resource_property(LineItem, 'tracking_tags')
# sdk-only
resource_property(LineItem, 'to_delete', transform=TRANSFORM.BOOL)

@@ -20,15 +20,15 @@ class PromotedAccount(Resource, Persistence):

# promoted account properties
# read-only
resource_property(PromotedAccount, 'id', readonly=True)
resource_property(PromotedAccount, 'approval_status', readonly=True)
resource_property(PromotedAccount, 'created_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(PromotedAccount, 'updated_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(PromotedAccount, 'deleted', readonly=True, transform=TRANSFORM.BOOL)
resource_property(PromotedAccount, 'entity_status', readonly=True)
resource_property(PromotedAccount, 'id', readonly=True)
resource_property(PromotedAccount, 'updated_at', readonly=True, transform=TRANSFORM.TIME)
# writable
resource_property(PromotedAccount, 'line_item_id')
resource_property(PromotedAccount, 'user_id')
resource_property(PromotedAccount, 'paused', transform=TRANSFORM.BOOL)


class PromotedTweet(Resource, Persistence, Analytics):
@@ -58,12 +58,12 @@ def save(self):

# promoted tweet properties
# read-only
resource_property(PromotedTweet, 'id', readonly=True)
resource_property(PromotedTweet, 'approval_status', readonly=True)
resource_property(PromotedTweet, 'created_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(PromotedTweet, 'updated_at', readonly=True, transform=TRANSFORM.TIME)
resource_property(PromotedTweet, 'deleted', readonly=True, transform=TRANSFORM.BOOL)
resource_property(PromotedTweet, 'paused', readonly=True, transform=TRANSFORM.BOOL)
resource_property(PromotedTweet, 'entity_status', readonly=True)
resource_property(PromotedTweet, 'id', readonly=True)
resource_property(PromotedTweet, 'updated_at', readonly=True, transform=TRANSFORM.TIME)
# writable
resource_property(PromotedTweet, 'line_item_id')
resource_property(PromotedTweet, 'tweet_id') # SDK limitation
@@ -15,6 +15,29 @@ def enum(**enums):
OBJECT=4
)

AGE_BUCKET = enum(
AGE_13_TO_24='AGE_13_TO_24',
AGE_13_TO_34='AGE_13_TO_34',
AGE_13_TO_49='AGE_13_TO_49',
AGE_13_TO_54='AGE_13_TO_54',
AGE_OVER_13='AGE_OVER_13',
AGE_18_TO_34='AGE_18_TO_34',
AGE_18_TO_49='AGE_18_TO_49',
AGE_18_TO_54='AGE_18_TO_54',
AGE_OVER_18='AGE_OVER_18',
AGE_21_TO_34='AGE_21_TO_34',
AGE_21_TO_49='AGE_21_TO_49',
AGE_21_TO_54='AGE_21_TO_54',
AGE_OVER_21='AGE_OVER_21',
AGE_25_TO_49='AGE_25_TO_49',
AGE_25_TO_54='AGE_25_TO_54',
AGE_OVER_25='AGE_OVER_25',
AGE_35_TO_49='AGE_35_TO_49',
AGE_35_TO_54='AGE_35_TO_54',
AGE_OVER_35='AGE_OVER_35',
AGE_OVER_50='AGE_OVER_50'
)

BID_UNIT = enum(
APP_CLICK='APP_CLICK',
APP_INSTALL='APP_INSTALL',
@@ -35,21 +58,56 @@ def enum(**enums):
VIEW='VIEW'
)

OPTIMIZATIONS = enum(
DEFAULT='DEFAULT',
WEBSITE_CONVERSIONS='WEBSITE_CONVERSIONS'
CREATIVE_TYPE = enum(
BANNER='BANNER',
INTERSTITIAL='INTERSTITIAL',
PREROLL='PREROLL',
VAST_PREROLL='VAST_PREROLL',
MEDIUM_RECTANGLE='MEDIUM_RECTANGLE',
BANNER_TABLET='BANNER_TABLET',
INTERSTITIAL_LANDSCAPE='INTERSTITIAL_LANDSCAPE',
INTERSTITIAL_TABLET='INTERSTITIAL_TABLET',
INTERSTITIAL_LANDSCAPE_TABLET='INTERSTITIAL_LANDSCAPE_TABLET'
)

PRODUCT = enum(
PROMOTED_ACCOUNT='PROMOTED_ACCOUNT',
PROMOTED_TWEETS='PROMOTED_TWEETS'
ENTITY = enum(
ACCOUNT='ACCOUNT',
FUNDING_INSTRUMENT='FUNDING_INSTRUMENT',
CAMPAIGN='CAMPAIGN',
LINE_ITEM='LINE_ITEM',
PROMOTED_TWEET='PROMOTED_TWEET',
ORGANIC_TWEET='ORGANIC_TWEET',
TARGETING_CRITERION='TARGETING_CRITERION'
)

PLACEMENT = enum(
ALL_ON_TWITTER='ALL_ON_TWITTER',
TWITTER_SEARCH='TWITTER_SEARCH',
TWITTER_TIMELINE='TWITTER_TIMELINE',
PUBLISHER_NETWORK='PUBLISHER_NETWORK'
ENTITY_STATUS = enum(
ACTIVE="ACTIVE",
DRAFT="DRAFT",
PAUSED="PAUSED"
)

EVENTS = enum(
MUSIC_AND_ENTERTAINMENT='MUSIC_AND_ENTERTAINMENT',
SPORTS='SPORTS',
HOLIDAY='HOLIDAY',
CONFERENCE='CONFERENCE',
OTHER='OTHER'
)

GRANULARITY = enum(
HOUR='HOUR',
DAY='DAY',
TOTAL='TOTAL'
)

METRIC_GROUP = enum(
ENGAGEMENT='ENGAGEMENT',
WEB_CONVERSION='WEB_CONVERSION',
MOBILE_CONVERSION='MOBILE_CONVERSION',
MEDIA='MEDIA',
VIDEO='VIDEO',
BILLING='BILLING',
LIFE_TIME_VALUE_MOBILE_CONVERSION='LIFE_TIME_VALUE_MOBILE_CONVERSION'
)

OBJECTIVE = enum(
@@ -65,41 +123,26 @@ def enum(**enums):
WEBSITE_CONVERSIONS='WEBSITE_CONVERSIONS'
)

GRANULARITY = enum(
HOUR='HOUR',
DAY='DAY',
TOTAL='TOTAL'
OPTIMIZATIONS = enum(
DEFAULT='DEFAULT',
WEBSITE_CONVERSIONS='WEBSITE_CONVERSIONS'
)

AGE_BUCKET = enum(
AGE_13_TO_24='AGE_13_TO_24',
AGE_13_TO_34='AGE_13_TO_34',
AGE_13_TO_49='AGE_13_TO_49',
AGE_13_TO_54='AGE_13_TO_54',
AGE_OVER_13='AGE_OVER_13',
AGE_18_TO_34='AGE_18_TO_34',
AGE_18_TO_49='AGE_18_TO_49',
AGE_18_TO_54='AGE_18_TO_54',
AGE_OVER_18='AGE_OVER_18',
AGE_21_TO_34='AGE_21_TO_34',
AGE_21_TO_49='AGE_21_TO_49',
AGE_21_TO_54='AGE_21_TO_54',
AGE_OVER_21='AGE_OVER_21',
AGE_25_TO_49='AGE_25_TO_49',
AGE_25_TO_54='AGE_25_TO_54',
AGE_OVER_25='AGE_OVER_25',
AGE_35_TO_49='AGE_35_TO_49',
AGE_35_TO_54='AGE_35_TO_54',
AGE_OVER_35='AGE_OVER_35',
AGE_OVER_50='AGE_OVER_50'
PERMISSION_LEVEL = enum(
READ_ONLY='READ_ONLY',
READ_WRITE='READ_WRITE'
)

EVENTS = enum(
MUSIC_AND_ENTERTAINMENT='MUSIC_AND_ENTERTAINMENT',
SPORTS='SPORTS',
HOLIDAY='HOLIDAY',
CONFERENCE='CONFERENCE',
OTHER='OTHER'
PLACEMENT = enum(
ALL_ON_TWITTER='ALL_ON_TWITTER',
TWITTER_SEARCH='TWITTER_SEARCH',
TWITTER_TIMELINE='TWITTER_TIMELINE',
PUBLISHER_NETWORK='PUBLISHER_NETWORK'
)

PRODUCT = enum(
PROMOTED_ACCOUNT='PROMOTED_ACCOUNT',
PROMOTED_TWEETS='PROMOTED_TWEETS'
)

TA_LIST_TYPES = enum(
@@ -115,49 +158,3 @@ def enum(**enums):
REMOVE='REMOVE',
REPLACE='REPLACE'
)

PERMISSION_LEVEL = enum(
READ_ONLY='READ_ONLY',
READ_WRITE='READ_WRITE'
)

# Analytics v1
METRIC_GROUP = enum(
ENGAGEMENT='ENGAGEMENT',
WEB_CONVERSION='WEB_CONVERSION',
MOBILE_CONVERSION='MOBILE_CONVERSION',
MEDIA='MEDIA',
VIDEO='VIDEO',
BILLING='BILLING',
LIFE_TIME_VALUE_MOBILE_CONVERSION='LIFE_TIME_VALUE_MOBILE_CONVERSION'
)

JOB_STATUS = enum(
QUEUED='QUEUED',
PROCESSING='PROCESSING',
UPLOADING='UPLOADING',
SUCCESS='SUCCESS',
FAILED='FAILED'
)

ENTITY = enum(
ACCOUNT='ACCOUNT',
FUNDING_INSTRUMENT='FUNDING_INSTRUMENT',
CAMPAIGN='CAMPAIGN',
LINE_ITEM='LINE_ITEM',
PROMOTED_TWEET='PROMOTED_TWEET',
ORGANIC_TWEET='ORGANIC_TWEET',
TARGETING_CRITERION='TARGETING_CRITERION'
)

CREATIVE_TYPE = enum(
BANNER='BANNER',
INTERSTITIAL='INTERSTITIAL',
PREROLL='PREROLL',
VAST_PREROLL='VAST_PREROLL',
MEDIUM_RECTANGLE='MEDIUM_RECTANGLE',
BANNER_TABLET='BANNER_TABLET',
INTERSTITIAL_LANDSCAPE='INTERSTITIAL_LANDSCAPE',
INTERSTITIAL_TABLET='INTERSTITIAL_TABLET',
INTERSTITIAL_LANDSCAPE_TABLET='INTERSTITIAL_LANDSCAPE_TABLET'
)