def test_returns_error_if_api_call_fails(self): self.add_response( body='{"errors":[{"message":"Rate limit exceeded","code":88}]}', status=429) result = FavoriteTweetsFetcher(screen_name='jill').fetch() self.assertFalse(result[0]['success']) self.assertIn('Rate limit exceeded', result[0]['messages'][0])
def test_fetches_multiple_pages_for_count(self): "Fetches subsequent pages until enough counted tweets are returned." qs = { 'user_id': self.account_1.user.twitter_id, 'count': 200, 'tweet_mode': 'extended', 'include_entities': 'true', } # Return "[{id:999}, {id:998}, {id:997},...]" and patch _save_results() # as we're only interested in how many times we ask for more results. body = json.dumps([{'id': x} for x in reversed(range(800, 1000))]) # We're going to request 3 x 200 Tweets and then... # ...1 x 100 Tweets = 700 Tweets. self.add_response(body=body, querystring=qs, match_querystring=True) qs['max_id'] = 799 self.add_response(body=body, querystring=qs, match_querystring=True) qs['max_id'] = 599 self.add_response(body=body, querystring=qs, match_querystring=True) qs['max_id'] = 399 qs['count'] = 100 self.add_response(body=body, querystring=qs, match_querystring=True) with patch.object(FetchTweetsFavorite, '_save_results'): with patch('time.sleep'): result = FavoriteTweetsFetcher(screen_name='jill').fetch( count=700) self.assertEqual(4, len(responses.calls))
def test_associates_users_with_favorites(self): self.add_response(body=self.make_response_body()) result = FavoriteTweetsFetcher(screen_name='jill').fetch() jill = User.objects.get(screen_name='jill') jills_faves = jill.favorites.all() self.assertEqual(len(jills_faves), 3) self.assertIsInstance(jills_faves[0], Tweet) self.assertEqual(jills_faves[0].twitter_id, 300)
def test_includes_count(self): "If fetching a number of tweets, requests that number, not since_id" body = json.dumps([{'id': 1} for x in range(25)]) self.add_response(body=body) with patch.object(FetchTweetsFavorite, '_save_results'): result = FavoriteTweetsFetcher(screen_name='jill').fetch(count=25) self.assertIn('count=25', responses.calls[0][0].url) self.assertNotIn('since_id=100', responses.calls[0][0].url)
def test_returns_correct_success_response(self): "Data returned is correct" self.add_response(body=self.make_response_body()) result = FavoriteTweetsFetcher().fetch() self.assertEqual(len(result), 2) self.assertEqual(result[1]['account'], 'jill') self.assertTrue(result[1]['success']) self.assertEqual(result[1]['fetched'], 3)
def test_updates_last_favorite_id_new(self): "The account's last_favorite_id should be set to the most recent tweet's" self.account_1.last_favorite_id = 9876543210 self.account_1.save() self.add_response(body=self.make_response_body()) result = FavoriteTweetsFetcher(screen_name='jill').fetch() self.account_1.refresh_from_db() self.assertEqual(self.account_1.last_favorite_id, 300)
def test_returns_error_if_no_creds(self): "If an account has no API credentials, the result is correct" user = UserFactory(screen_name='bobby') account = AccountFactory(user=user) self.add_response(body=self.make_response_body()) result = FavoriteTweetsFetcher(screen_name='bobby').fetch() self.assertFalse(result[0]['success']) self.assertIn('Account has no API credentials', result[0]['messages'][0])
def test_ignores_account_with_no_creds(self, download): # This will just stop us requesting avatars from Twitter: download.side_effect = DownloadException('Ooops') # Add a third Account that has no API credentials: account_3 = AccountFactory(user=UserFactory()) self.add_response(body=self.make_response_body()) result = FavoriteTweetsFetcher().fetch() # Should only have fetched faves for the two accounts with API creds: self.assertEqual(2, len(responses.calls))
def test_saves_correct_tweet_data(self, save_tweet): """Assert save_tweet is called once per tweet. Not actually checking what's passed in.""" save_tweet.side_effect = [ TweetFactory(), TweetFactory(), TweetFactory() ] self.add_response(body=self.make_response_body()) result = FavoriteTweetsFetcher(screen_name='jill').fetch() self.assertEqual(save_tweet.call_count, 3)
def test_updates_last_favorite_id_count(self): """The account's last_favorite_id should be changed if requesting count tweets """ self.account_1.last_favorite_id = 9876543210 self.account_1.save() body = json.dumps([{'id': 999} for x in range(25)]) self.add_response(body=body) with patch.object(FetchTweetsFavorite, '_save_results'): result = FavoriteTweetsFetcher(screen_name='jill').fetch(count=25) self.account_1.refresh_from_db() self.assertEqual(self.account_1.last_favorite_id, 999)
def test_fetches_multiple_pages_for_new(self, download): """Fetches subsequent pages until no results are returned.""" # This will just stop us requesting avatars from Twitter: download.side_effect = DownloadException('Ooops') self.account_1.last_favorite_id = 10 self.account_1.save() qs = { 'user_id': self.account_1.user.twitter_id, 'count': 200, 'since_id': 10 } self.add_response(body=self.make_response_body(), querystring=qs, match_querystring=True) qs['max_id'] = 99 self.add_response(body='[]', querystring=qs, match_querystring=True) with patch('time.sleep'): result = FavoriteTweetsFetcher(screen_name='jill').fetch() self.assertEqual(2, len(responses.calls))
def test_saves_tweets(self): self.add_response(body=self.make_response_body()) result = FavoriteTweetsFetcher(screen_name='jill').fetch() self.assertEqual(Tweet.objects.count(), 3) # Our sample tweets are from a different user, so there'll now be 3: self.assertEqual(User.objects.count(), 3)
def test_omits_last_favorite_id_from_response(self): "If an account has no last_favorite_id, it is not used in the request" # Stop us fetching multiple pages of results: self.add_response(body='[]') result = FavoriteTweetsFetcher(screen_name='jill').fetch() self.assertFalse('since_id=9876543210' in responses.calls[0][0].url)
def test_includes_last_favorite_id_in_response(self): "If an account has a last_favorite_id, use it in the request" self.add_response(body=self.make_response_body()) result = FavoriteTweetsFetcher(screen_name='jill').fetch() self.assertTrue('since_id=100' in responses.calls[0][0].url)
def test_api_requests_for_all_accounts(self, download): # This will just stop us requesting avatars from Twitter: download.side_effect = DownloadException('Ooops') self.add_response(body=self.make_response_body()) result = FavoriteTweetsFetcher().fetch() self.assertEqual(2, len(responses.calls))