"""Unit tests for streams models layer.""" from unittest.mock import MagicMock, patch import flexmock import pytest from snowflake_connector.snowflake_conn import SQLLoader from analytics.consts import models as model_consts from analytics.models import streams @pytest.fixture() def mock_snowflake(monkeypatch, mock_config): """Mock for Snowflake database client.""" snowflake_mock = MagicMock() monkeypatch.setattr( 'analytics.models.streams.snowflake_conn', snowflake_mock) return snowflake_mock def test_get_streams_sql_adds_all_clauses_when_all_present(streams_params): """Test that the correct clauses are added to the raw sql statement.""" mock_sql_string = ( '{subaccount_clause}{isrcs_clause}{storeid_clause}{artistids_clause}') expected_final_sql = ( 'AND subaccountid = :subaccountidAND isrc in (:isrcs)' 'AND storeid in (:storeids)AND artistid in (:artistids)') (flexmock(SQLLoader).should_receive('load_query').with_args( 'get_streams').and_return(mock_sql_string).once()) result = streams._get_streams_sql(streams_params) assert result == expected_final_sql def test_get_streams_sql_adds_all_clauses_when_none_present(): """Test that no clauses are added to the raw sql statement.""" mock_sql_string = ( '{subaccount_clause}{isrcs_clause}{storeid_clause}{artistids_clause}') (flexmock(SQLLoader).should_receive('load_query').with_args( 'get_streams').and_return(mock_sql_string).once()) result = streams._get_streams_sql({}) assert result == '' def test_get_streams_returns_expected_message( streams_params, mock_snowflake, streams_db_result, streams_formatted_result_with_full_dates): """Test expected result returned when successful call executed.""" fake_sql_string = 'SELECT * FROM faketable' (flexmock(streams).should_receive('_get_streams_sql').with_args( streams_params).and_return(fake_sql_string)) mock_snowflake.fetchall.return_value = streams_db_result result = streams.get_streams(**streams_params) assert result.status == 200 assert result.message == streams_formatted_result_with_full_dates def test_get_streams_returns_empty_list_when_no_data_found( streams_params, mock_snowflake): """Test full results with zero results when no data found.""" fake_sql_string = 'SELECT * FROM faketable' (flexmock(streams).should_receive('_get_streams_sql').with_args( streams_params).and_return(fake_sql_string)) mock_snowflake.fetchall.return_value = [] result = streams.get_streams(**streams_params) assert result.status == 200 assert result.message == [ { 'streams_from_collection': 0, 'date': '2017-08-01', 'overall_number_of_streams': 0, 'streams_from_passive_discovery': 0, 'streams_from_active_discovery': 0}, { 'streams_from_collection': 0, 'date': '2017-08-02', 'overall_number_of_streams': 0, 'streams_from_passive_discovery': 0, 'streams_from_active_discovery': 0}, { 'streams_from_collection': 0, 'date': '2017-08-03', 'overall_number_of_streams': 0, 'streams_from_passive_discovery': 0, 'streams_from_active_discovery': 0}] def test_get_streams_returns_empty_list_when_no_data_found_v2( streams_params, mock_snowflake): """Test full results with zero results when no data found.""" fake_sql_string = 'SELECT * FROM faketable' (flexmock(streams).should_receive('_get_streams_sql_v2').with_args( streams_params).and_return(fake_sql_string)) mock_snowflake.fetchall.return_value = [] result = streams.get_streams_v2(**streams_params) assert result.status == 200 assert result.message == [ { 'streams_from_collection': 0, 'date': '2017-08-01', 'overall_number_of_streams': 0, 'overall_number_of_spotify_streams': 0, 'streams_from_passive_discovery': 0, 'streams_from_active_discovery': 0, 'skips': 0, 'saves': 0}, { 'streams_from_collection': 0, 'date': '2017-08-02', 'overall_number_of_streams': 0, 'overall_number_of_spotify_streams': 0, 'streams_from_passive_discovery': 0, 'streams_from_active_discovery': 0, 'skips': 0, 'saves': 0}, { 'streams_from_collection': 0, 'date': '2017-08-03', 'overall_number_of_streams': 0, 'overall_number_of_spotify_streams': 0, 'streams_from_passive_discovery': 0, 'streams_from_active_discovery': 0, 'skips': 0, 'saves': 0}] class TestBuildPlacementsSql(object): """Test build_get_placements_sql.""" sql_file = 'get_placements' def test_adds_all_clauses_when_all_present(self, placement_params): """Test that the correct clauses are added to the raw sql statement.""" mock_sql_string = ( '{subaccountid}{subaccount_clause}{isrcs_clause}{storeid_clause}' '{artistids_clause}{limit_clause}') expected_final_sql = ( 'subaccountid,AND subaccountid = :subaccountidAND isrc in (:isrcs)' 'AND storeid in (:storeids)AND artistid in (:artistids)' 'LIMIT :limit') (flexmock(SQLLoader).should_receive('load_query').with_args( self.sql_file).and_return(mock_sql_string).once()) result = streams.build_placements_sql(self.sql_file, placement_params) assert result == expected_final_sql def test_adds_all_clauses_when_none_present(self): """Test that no clauses are added to the raw sql statement.""" mock_sql_string = ( '{subaccount_clause}{isrcs_clause}' '{storeid_clause}{artistids_clause}{limit_clause}') (flexmock(SQLLoader).should_receive('load_query').with_args( self.sql_file).and_return(mock_sql_string).once()) result = streams.build_placements_sql(self.sql_file, {}) assert result == '' class TestGetPlacements(object): """Test get_placements.""" streams_path = 'analytics.models.streams' @pytest.yield_fixture def mock_build_placements_sql(self): """Mock the _get_placements sql builder.""" build_get_placements_sql_path = self.streams_path + \ '.build_placements_sql' with patch(build_get_placements_sql_path) as build_get_placements_sql: build_get_placements_sql.return_value = 'SELECT * FROM faketable' yield build_get_placements_sql @pytest.yield_fixture def mock_format_query_result(self): """Mock _format_query_result helper function.""" format_query_result_path = ( self.streams_path + '._format_query_result') with patch(format_query_result_path) as format_query_result: yield format_query_result @pytest.fixture def get_placements_success( self, placement_params, streams_placements_db_result, mock_build_placements_sql, mock_snowflake): """Make call to get_placements as if there was a payload.""" mock_snowflake.fetchall.return_value = streams_placements_db_result return streams.get_placements(**placement_params) def test_returns_succussfully(self, get_placements_success): """Test correct response returned when successful call executed.""" assert get_placements_success.status == 200 def test_returns_with_placement_data( self, get_placements_success, streams_placements_db_formatted_result): """Test message is what is expected.""" message = get_placements_success.message assert message == streams_placements_db_formatted_result def test_constructs_sql_with_streams_params( self, placement_params, mock_build_placements_sql, get_placements_success): """Test SQL get constructed.""" mock_build_placements_sql.assert_called_with( 'get_placements', placement_params) def test_proper_result_formatting( self, mock_format_query_result, mock_snowflake, get_placements_success): """Test data formatted with proper column list.""" mock_format_query_result.assert_called_with( mock_snowflake.fetchall.return_value, model_consts.SOS_PLACEMENTS) @pytest.fixture def get_placements_no_data( self, placement_params, mock_build_placements_sql, mock_snowflake): """Return empty list as if there were no data.""" mock_snowflake.fetchall.return_value = [] return streams.get_placements(**placement_params) def test_returns_empty_list_when_no_data(self, get_placements_no_data): """Test empty list returned when no placements data found.""" assert get_placements_no_data.message == [] def test_returns_success_response_when_no_data( self, get_placements_no_data): """Test success response when no placements data found.""" assert get_placements_no_data.status == 200 class TestGetPlacementTotals(object): """Test get_placements.""" streams_path = 'analytics.models.streams' placement_totals = 1237 @pytest.yield_fixture def mock_build_placements_sql(self): """Mock the _get_placements sql builder.""" build_get_placements_sql_path = self.streams_path + \ '.build_placements_sql' with patch(build_get_placements_sql_path) as build_get_placements_sql: build_get_placements_sql.return_value = 'SELECT * FROM faketable' yield build_get_placements_sql @pytest.fixture def get_placement_totals_success( self, streams_params, mock_build_placements_sql, mock_snowflake): """Make call to get_placements as if there was a payload.""" mock_snowflake.fetchone.return_value = (self.placement_totals, ) return streams.get_placement_totals(**streams_params) def test_returns_succussfully(self, get_placement_totals_success): """Test correct response returned when successful call executed.""" assert get_placement_totals_success.status == 200 def test_returns_with_placement_data( self, get_placement_totals_success, streams_placements_db_formatted_result): """Test message is what is expected.""" message = get_placement_totals_success.message assert message == self.placement_totals def test_constructs_sql_with_streams_params( self, streams_params, mock_build_placements_sql, get_placement_totals_success): """Test SQL get constructed.""" mock_build_placements_sql.assert_called_with( 'get_placement_totals', streams_params) @pytest.fixture def get_placement_totals_no_data( self, streams_params, mock_build_placements_sql, mock_snowflake): """Return empty list as if there were no data.""" mock_snowflake.fetchone.return_value = ((),) return streams.get_placement_totals(**streams_params) def test_returns_none_when_no_data( self, get_placement_totals_no_data): """Test empty list returned when no placements data found.""" assert get_placement_totals_no_data.message == 0 def test_returns_success_response_when_no_data( self, get_placement_totals_no_data): """Test success response when no placements data found.""" assert get_placement_totals_no_data.status == 200