"""Tests for collector.""" import csv import json import os from unittest.mock import MagicMock from unittest.mock import patch from botocore.exceptions import ClientError from freezegun import freeze_time import pytest from social_analytics import config from social_analytics.logic import collector from social_analytics.logic import facebook_collector from social_analytics.logic import instagram_collector from social_analytics.logic import spotify_collector @pytest.fixture def upload_raw_json_params(): """Fixture for upload raw data.""" return [ { 'social_profile_id': 1, 'platform': 'facebook', 'data_response': { 'test': 'test' } }, { 'social_profile_id': 1, 'platform': 'instagram', 'data_response': { 'test': 'test' } }, { 'social_profile_id': 3, 'platform': 'spotify', 'data_response': { 'test': 'test' } } ] @pytest.fixture(params=['facebook', 'instagram', 'spotify']) def platform_params(request): """Fixture for retrieve social profiles for platform.""" return request.param def test_get_tokens(monkeypatch): """Test get tokens.""" monkeypatch.setattr( config, 'FACEBOOK_IS_ACTIVE', MagicMock(return_value='Active')) monkeypatch.setattr( config, 'INSTAGRAM_IS_ACTIVE', MagicMock(return_value='Active')) monkeypatch.setattr( config, 'SPOTIFY_IS_ACTIVE', MagicMock(return_value='Active')) monkeypatch.setattr( facebook_collector, 'refresh_token', MagicMock(return_value='123')) monkeypatch.setattr( instagram_collector, 'refresh_token', MagicMock(return_value='456')) monkeypatch.setattr( spotify_collector, 'refresh_token', MagicMock( return_value={ 'access_token': '789', 'token_type': 'Bearer', 'scope': 'user-read-private user-read-email', 'expires_in': 3600, 'refresh_token': 'NgAagAUm_SHo' } )) expected = { 'facebook': '123', 'instagram': '456', 'spotify': '789' } result = collector.get_tokens() assert result assert result == expected def test_collect_no_platform(): """Test collect no platform.""" collect_params = { 'social_profile': { 'platform': 'other', 'social_profile_id': 123, 'label_id': 456 }, 'tokens': {} } result = collector.collect(collect_params) assert not result def test_collect_facebook(monkeypatch): """Test collect for facebook.""" monkeypatch.setattr( facebook_collector, 'collect_facebook_metrics', MagicMock()) collect_params = { 'social_profile': { 'platform': 'facebook', 'platform_id': '15', 'social_profile_id': 123, 'label_id': 456 }, 'tokens': { 'facebook': 'token' } } result = collector.collect(collect_params) facebook_collector.collect_facebook_metrics.assert_called_once_with( collect_params['social_profile']['platform_id'], collect_params['tokens']['facebook']) assert result assert result['data_response'] def test_collect_instagram(monkeypatch): """Test collect for instagram.""" monkeypatch.setattr( instagram_collector, 'collect_instagram_metrics', MagicMock()) collect_params = { 'social_profile': { 'platform': 'instagram', 'platform_id': '15', 'social_profile_id': 123, 'label_id': 456 }, 'tokens': { 'instagram': 'token' } } result = collector.collect(collect_params) instagram_collector.collect_instagram_metrics.assert_called_once_with( collect_params['social_profile']['platform_id'], collect_params['tokens']['instagram']) assert result assert result['data_response'] def test_collect_spotify(monkeypatch): """Test collect for spotify.""" monkeypatch.setattr( spotify_collector, 'collect_spotify_metrics', MagicMock()) collect_params = { 'social_profile': { 'platform': 'spotify', 'platform_id': '15', 'social_profile_id': 123, 'label_id': 456 }, 'tokens': {'spotify': 'token'} } result = collector.collect(collect_params) spotify_collector.collect_spotify_metrics.assert_called_once_with( collect_params['social_profile']['platform_id'], collect_params['tokens']['spotify']) assert result assert result['data_response'] @patch.object(collector, 'uuid4', side_effect=['123']) @freeze_time('2017-04-15 14:45:4') def test_generate_metrics_remote_file_name(self): """Test generate remote file name.""" expected = 'social-collection/2017/4/15/14/45/4/123.csv' result = collector.generate_metrics_remote_file_name() assert result assert result == expected @patch('social_analytics.logic.collector.os.remove') def test_upload_file_to_s3(mock_os, monkeypatch): """Test upload to s3.""" client = MagicMock() monkeypatch.setattr(collector.boto3, 'client', client) response = collector.upload_file_to_s3('123.csv', '123') client.assert_called_once_with( 's3', aws_access_key_id=config.AWS_ACCESS_KEY, aws_secret_access_key=config.AWS_SECRET_KEY) client.return_value.upload_file.assert_called_once_with( '123.csv', config.AWS_S3_BUCKET, '123') mock_os.assert_called_with('123.csv') assert response is None @patch('social_analytics.logic.collector.os.remove') def test_upload_to_s3_exception(mock_os, monkeypatch): """Test upload to s3 exception.""" client = MagicMock() client.return_value.upload_file = MagicMock( side_effect=ClientError(MagicMock(), MagicMock())) monkeypatch.setattr(collector.boto3, 'client', client) result = collector.upload_file_to_s3('123.csv', '123') client.assert_called_once_with( 's3', aws_access_key_id=config.AWS_ACCESS_KEY, aws_secret_access_key=config.AWS_SECRET_KEY) client.return_value.upload_file.assert_called_once_with( '123.csv', config.AWS_S3_BUCKET, '123') mock_os.assert_called_with('123.csv') assert result def test_convert_social_profiles_to_csv(monkeypatch): """Test convert social_profiles_to_csv.""" social_profiles = [ { 'social_profile_id': 1, 'platform': 'spotify', 'label_id': 1, 'data_response': { 'followers': { 'href': None, 'total': 6573625 }, 'name': 'Taylor Swift', 'uri': 'spotify:artist:06HL' } } ] csv_row = [1, 1, 1, 1, 10000, '2017-09-14 18:48:07.280466', ''] csv_path = './social_profiles.csv' monkeypatch.setattr( collector, 'process_response', MagicMock(return_value=csv_row)) result = collector.convert_social_profiles_to_csv( social_profiles, csv_path) assert result with open(csv_path) as csvfile: reader = csv.reader(csvfile) for row in reader: if row: assert int(row[0]) == csv_row[0] assert int(row[1]) == csv_row[1] assert int(row[2]) == csv_row[2] assert int(row[3]) == csv_row[3] assert int(row[4]) == csv_row[4] assert row[5] == csv_row[5] assert row[6] == csv_row[6] os.remove(csv_path) @freeze_time('2017-09-14 18:48:07.280466') def test_process_response(): """Test the process_response.""" social_profile = { 'social_profile_id': 1, 'platform': 'spotify', 'data_response': { 'followers': { 'href': None, 'total': 6573625 }, 'name': 'Taylor Swift', 'uri': 'spotify:artist:06HL' } } collected_date = '2017-09-14 18:48:07.280466' activity_date = collected_date expected_result = [1, 3, '', 1, 6573625, collected_date, activity_date] result = collector.process_response(social_profile) assert result == expected_result def test_recommend_profile_for_social_network_facebook(monkeypatch): """Test recommend social profile for facebook.""" profile_search_params = { 'platform': 'facebook', 'platform_name': 'Jeff Buckley'} facebook_collector_response = { 'platform': 'facebook', 'platform_id': '1', 'platform_name': 'Jeff Buckley', 'is_verified': True} monkeypatch.setattr( facebook_collector, 'recommend_facebook_profile', MagicMock( return_value=facebook_collector_response)) result = collector.recommend_profile_for_social_network( profile_search_params) assert result def test_recommend_profile_for_social_network_facebook_not_found(monkeypatch): """Test recommend social profile for facebook not found.""" profile_search_params = { 'platform': 'facebook', 'platform_name': 'Jeff Buckley'} facebook_collector_response = None monkeypatch.setattr( facebook_collector, 'recommend_facebook_profile', MagicMock( return_value=facebook_collector_response)) result = collector.recommend_profile_for_social_network( profile_search_params) assert not result def test_recommend_profile_for_social_network_instagram(monkeypatch): """Test recommend social profile for instagram.""" profile_search_params = { 'platform': 'instagram', 'platform_name': 'Jeff Buckley'} instagram_collector_response = { 'platform': 'instagram', 'platform_id': '1', 'platform_name': 'Jeff Buckley'} monkeypatch.setattr( instagram_collector, 'recommend_instagram_profile', MagicMock( return_value=instagram_collector_response)) result = collector.recommend_profile_for_social_network( profile_search_params) assert result def test_recommend_profile_for_social_network_instagram_not_found(monkeypatch): """Test recommend social profile for instagram not found.""" profile_search_params = { 'platform': 'instagram', 'platform_name': 'Jeff Buckley'} instagram_collector_response = None monkeypatch.setattr( instagram_collector, 'recommend_instagram_profile', MagicMock( return_value=instagram_collector_response)) result = collector.recommend_profile_for_social_network( profile_search_params) assert not result def test_recommend_profile_for_social_network_spotify(monkeypatch): """Test recommend social profile for spotify.""" profile_search_params = { 'platform': 'spotify', 'platform_name': 'Jeff Buckley'} spotify_collector_response = { 'platform': 'spotify', 'platform_id': '1', 'platform_name': 'Jeff Buckley'} monkeypatch.setattr( spotify_collector, 'recommend_spotify_profile', MagicMock( return_value=spotify_collector_response)) result = collector.recommend_profile_for_social_network( profile_search_params) assert result def test_recommend_profile_for_social_network_spotify_not_found(monkeypatch): """Test recommend social profile for spotify not found.""" profile_search_params = { 'platform': 'spotify', 'platform_name': 'Jeff Buckley'} spotify_collector_response = None monkeypatch.setattr( spotify_collector, 'recommend_spotify_profile', MagicMock( return_value=spotify_collector_response)) result = collector.recommend_profile_for_social_network( profile_search_params) assert not result def test_verify_profile_for_social_network_facebook(monkeypatch): """Test verify social profile for facebook.""" profile_search_params = { 'platform': 'facebook', 'platform_id': 123} facebook_collector_response = { 'platform': 'facebook', 'platform_id': '1', 'platform_name': 'Jeff Buckley', 'is_verified': True} monkeypatch.setattr( facebook_collector, 'verify_facebook_profile', MagicMock( return_value=facebook_collector_response)) result = collector.recommend_profile_for_social_network( profile_search_params) assert result def test_verify_profile_for_social_network_facebook_not_found(monkeypatch): """Test verify social profile for facebook not found.""" profile_search_params = { 'platform': 'facebook', 'platform_id': '123123'} facebook_collector_response = None monkeypatch.setattr( facebook_collector, 'verify_facebook_profile', MagicMock( return_value=facebook_collector_response)) result = collector.recommend_profile_for_social_network( profile_search_params) assert not result def test_verify_profile_for_social_network_instagram(monkeypatch): """Test verify social profile for instagram.""" profile_search_params = { 'platform': 'instagram', 'platform_id': '123'} instagram_collector_response = { 'platform': 'instagram', 'platform_id': '123', 'platform_name': 'Jeff Buckley'} monkeypatch.setattr( instagram_collector, 'verify_instagram_profile', MagicMock( return_value=instagram_collector_response)) result = collector.recommend_profile_for_social_network( profile_search_params) assert result def test_verify_profile_for_social_network_instagram_not_found(monkeypatch): """Test verify social profile for instagram not found.""" profile_search_params = { 'platform': 'instagram', 'platform_id': '123'} instagram_collector_response = None monkeypatch.setattr( instagram_collector, 'verify_instagram_profile', MagicMock( return_value=instagram_collector_response)) result = collector.recommend_profile_for_social_network( profile_search_params) assert not result def test_verify_profile_for_social_network_spotify(monkeypatch): """Test verify social profile for spotify.""" profile_search_params = { 'platform': 'spotify', 'platform_id': 'AAAGGGx1231231'} spotify_collector_response = { 'platform': 'spotify', 'platform_id': 'AAAGGGx1231231', 'platform_name': 'Jeff Buckley'} monkeypatch.setattr( spotify_collector, 'verify_spotify_profile', MagicMock( return_value=spotify_collector_response)) result = collector.recommend_profile_for_social_network( profile_search_params) assert result def test_verify_profile_for_social_network_spotify_not_found(monkeypatch): """Test verify social profile for spotify not found.""" profile_search_params = { 'platform': 'spotify', 'platform_id': 'AAAGGGx1231231'} spotify_collector_response = None monkeypatch.setattr( spotify_collector, 'verify_spotify_profile', MagicMock( return_value=spotify_collector_response)) result = collector.recommend_profile_for_social_network( profile_search_params) assert not result def test_recommend_profile_for_social_network_spotify_bad_params(monkeypatch): """Test recommend social profile for spotify with bad params.""" profile_search_params = { 'platform_name': 'Jeff Buckley'} result = collector.recommend_profile_for_social_network( profile_search_params) assert not result errors = result.errors assert errors['message'] == 'Bad Params' def test_recommend_profile_for_social_network_spotify_bad_params_no_network( monkeypatch): """Test recommend social profile not found with bad params.""" profile_search_params = { 'platform': 'twitter', 'platform_name': 'Jeff Buckley'} result = collector.recommend_profile_for_social_network( profile_search_params) assert not result def test_recommend_profile_for_social_network_spotify_bad_params_no_id_or_name( monkeypatch): """Test recommend social profile not found with bad params.""" profile_search_params = { 'platform': 'facebook'} result = collector.recommend_profile_for_social_network( profile_search_params) assert not result def test_recommend_profile_for_social_network_spotify_bad_params_id_and_name( monkeypatch): """Test recommend social profile not found with bad params.""" profile_search_params = { 'platform': 'facebook', 'platform_name': 'Malevolent Creation', 'platform_id': '123AAA'} result = collector.recommend_profile_for_social_network( profile_search_params) assert not result def test_create_raw_data_json_file(): """Test create raw data json file.""" raw_data = [ { 'id': '123', 'is_verified': True, 'fan_count': 74114459, 'talking_about_count': 126025, 'name': 'Taylor Swift', 'username': 'TaylorSwift' }, { 'id': '345', 'is_verified': True, 'fan_count': 10000, 'talking_about_count': 126026, 'name': 'Mindless Self Indulgence', 'username': 'msi' }] result = collector.create_raw_data_json_file(raw_data) assert result with open(result) as data_file: data_items = json.load(data_file) assert len(data_items) == 2 os.remove(result) def test_generate_raw_data_remote_json_file_name(): """Test create remote json file path.""" platform = 'facebook' date_as_timestamp = '1510698187' result = collector.generate_raw_data_remote_json_file_name( platform, date_as_timestamp) assert result assert result == 'social-collection-raw-data/facebook/1510698187/data.json' def test_upload_raw_json_to_s3(monkeypatch, upload_raw_json_params): """Test upload raw jton to s3.""" monkeypatch.setattr( collector, 'create_raw_data_json_file', MagicMock( return_value='raw_data.json')) monkeypatch.setattr( collector, 'generate_raw_data_remote_json_file_name', MagicMock( return_value='test')) monkeypatch.setattr( collector, 'upload_file_to_s3', MagicMock( side_effect=[None, None, None])) result = collector.upload_raw_json_to_s3(upload_raw_json_params) assert not result def test_upload_raw_json_to_s3_errors(monkeypatch, upload_raw_json_params): """Test upload raw jton to s3 error.""" monkeypatch.setattr( collector, 'create_raw_data_json_file', MagicMock( return_value='raw_data.json')) monkeypatch.setattr( collector, 'generate_raw_data_remote_json_file_name', MagicMock( return_value='test')) monkeypatch.setattr( collector, 'upload_file_to_s3', MagicMock( side_effect=[{'error'}, {'error'}, {'error'}])) result = collector.upload_raw_json_to_s3(upload_raw_json_params) assert result def test_upload_metrics_json_to_s3(monkeypatch): """Test upload metrics json to s3.""" monkeypatch.setattr( collector, 'convert_social_profiles_to_csv', MagicMock( return_value='123.csv')) monkeypatch.setattr( collector, 'generate_metrics_remote_file_name', MagicMock( return_value='social-collection/2017/4/15/14/45/4/123.csv')) monkeypatch.setattr( collector, 'upload_file_to_s3', MagicMock(return_value=None)) result = collector.upload_metrics_json_to_s3(MagicMock()) assert not result def test_upload_metrics_json_to_s3_error(monkeypatch): """Test upload metrics json to s3.""" monkeypatch.setattr( collector, 'convert_social_profiles_to_csv', MagicMock( return_value='123.csv')) monkeypatch.setattr( collector, 'generate_metrics_remote_file_name', MagicMock( return_value='social-collection/2017/4/15/14/45/4/123.csv')) monkeypatch.setattr( collector, 'upload_file_to_s3', MagicMock(return_value={'error'})) result = collector.upload_metrics_json_to_s3(MagicMock()) assert result def test_group_social_profiles_by_platform( platform_params, upload_raw_json_params): """Test retrieve social profiles for platform.""" result = collector.group_social_profiles_by_platform( platform_params, upload_raw_json_params) assert result assert len(result) == 1