"""Tests for Handlers.""" import json from unittest.mock import MagicMock from unittest.mock import patch from oto import response from sales_goals import handlers from sales_goals.constants import header from sales_goals.logic import countries from sales_goals.logic import digital_projections from sales_goals.logic import marketing_highlights from sales_goals.logic import ownership from sales_goals.logic import sales_goals @patch('sales_goals.handlers.g') def test_exception_handler(mock_g, app_context): """Verify exception_Handler returns 500 status code and json payload.""" message = ( 'The server encountered an internal error ' 'and was unable to complete your request.') mock_error = MagicMock() server_response = handlers.exception_handler(mock_error) mock_g.log.exception.assert_called_with(mock_error) # assert status code is 500 assert server_response.status_code == 500 # assert json payload response_message = json.loads(server_response.data.decode()) assert response_message['message'] == message assert response_message['code'] == response.error.ERROR_CODE_INTERNAL_ERROR def test_handler_get_goal_by_product_id_success( mocker, client, valid_get_header, valid_sales_goal): """Test `GET /goals/{productId}` handler success state.""" mocker.patch.object( sales_goals, 'fetch_by_product_id', return_value=response.Response(message=valid_sales_goal)) result = client.get('/goals/1234', headers=valid_get_header) assert result.status_code == 200 assert sales_goals.fetch_by_product_id.called def test_handler_get_goal_by_product_id_not_found_error( mocker, client, valid_get_header): """Test `GET /goals/{productId}` for product that doesn't exist.""" mocker.patch.object( sales_goals, 'fetch_by_product_id', return_value=response.create_not_found_response()) result = client.get('/goals/1234', headers=valid_get_header) assert result.status_code == 404 assert sales_goals.fetch_by_product_id.called def test_handler_sales_goal_create_success( mocker, client, valid_post_header, valid_sales_goals_creation_response): """Test `POST /goals/{productId}` handler success state.""" test_request_body = { 'sales_goals': { 'notes': '50' } } mocker.patch.object( sales_goals, 'create_for_product_id', return_value=response.Response( message=valid_sales_goals_creation_response)) result = client.post( '/goals/23234', headers=valid_post_header, data=json.dumps(test_request_body)) sales_goals.create_for_product_id.assert_called_once_with( product_id=23234, sales_goal_data=test_request_body, account_type='vendor', account_id='25257', user_id='alw:12345') assert result.status_code == 200 assert sales_goals.create_for_product_id.called def test_handler_sales_goal_create_with_hmv_notes( mocker, client, valid_post_header, valid_sales_goals_creation_response): """Test `POST /goals/{productId}` handler success state.""" test_request_body = { 'sales_goals': { 'hmv_notes': 'are provided' } } mocker.patch.object( sales_goals, 'create_for_product_id', return_value=response.Response( message=valid_sales_goals_creation_response)) result = client.post( '/goals/23234', headers=valid_post_header, data=json.dumps(test_request_body)) assert result.status_code == 200 def test_handler_countries_get_success( mocker, client, valid_get_header, valid_countries_get_response): """Test `GET /goals/countries` handler success state.""" mocker.patch.object( countries, 'get_countries', return_value=response.Response( message=valid_countries_get_response)) result = client.get('/goals/countries', headers=valid_get_header) assert result.status_code == 200 assert countries.get_countries.called def test_handler_get_territories_success( mocker, client, valid_get_header, valid_countries_get_response): """Test `GET /territories` handler success state.""" mocker.patch.object( countries, 'get_territories', return_value=response.Response( message=valid_countries_get_response)) result = client.get('/territories', headers=valid_get_header) assert result.status_code == 200 assert countries.get_territories.called def test_handler_sales_goal_update_success( mocker, client, valid_post_header, valid_sales_goals_creation_response): """Test `PATCH /goals/{productId}` handler success state.""" test_request_body = { 'notes': 'bang' } mocker.patch.object( sales_goals, 'update_for_product_id', return_value=response.Response( message=valid_sales_goals_creation_response)) result = client.patch( '/goals/23234', headers=valid_post_header, data=json.dumps(test_request_body)) sales_goals.update_for_product_id.assert_called_once_with( product_id=23234, sales_goal_data=test_request_body, account_type='vendor', account_id='25257', user_id='alw:12345') assert result.status_code == 200 assert sales_goals.update_for_product_id.called def test_handler_sales_goal_update_with_hmv_notes( mocker, client, valid_post_header, valid_sales_goals_creation_response): """Test `PATCH /goals/{productId}` handler success state.""" test_request_body = { 'hmv_notes': 'are provided' } mocker.patch.object( sales_goals, 'update_for_product_id', return_value=response.Response( message=valid_sales_goals_creation_response)) result = client.patch( '/goals/23234', headers=valid_post_header, data=json.dumps(test_request_body)) assert result.status_code == 200 def test_handler_target_market_goal_create_success( mocker, client, valid_post_header, valid_target_market_goal_creation_response): """Test `POST /goals/{productId}/{countryId}` handler success state.""" test_request_body = { 'goals': [ { 'store': { 'store_id': 1, 'name': 'Amazon', }, 'label_goal_value': 20, 'distribution_goal_value': 30, }]} mocker.patch.object( sales_goals, 'create_target_market_goal', return_value=response.Response( message=valid_target_market_goal_creation_response)) result = client.post( '/goals/23234/1', headers=valid_post_header, data=json.dumps(test_request_body)) sales_goals.create_target_market_goal.assert_called_once_with( product_id=23234, country_id=1, market_goal_data=test_request_body, account_type='vendor', account_id='25257', user_id='alw:12345') result_response = json.loads(result.data.decode('utf-8')) assert result.status_code == 200 assert sales_goals.create_target_market_goal.called assert result_response == valid_target_market_goal_creation_response def test_handler_target_market_goal_create_header_error( mocker, client, valid_post_header, valid_target_market_goal_creation_response): """Test `POST /goals/{productId}/{countryId}` handler fails on headers.""" mocker.patch.object( sales_goals, 'create_target_market_goal', return_value=response.Response( message=valid_target_market_goal_creation_response)) invalid_header = valid_post_header invalid_header[header.GRASS_ACCOUNT_TYPE] = 'foobar' result = client.post('/goals/1234/1', headers=invalid_header) assert result.status_code == 400 sales_goals.create_target_market_goal.assert_not_called() def test_handler_target_market_goal_delete_success( mocker, client, valid_post_header): """Test `DELETE /goals/{productId}/{countryId}` handler success state.""" product_id = 1 country_id = 1 resp = {'target_market_goal_id': 1} mocker.patch.object( sales_goals, 'delete_target_market_goal', return_value=response.Response( message=resp)) result = client.delete( '/goals/{product_id}/{country_id}'.format( product_id=product_id, country_id=country_id), headers=valid_post_header) sales_goals.delete_target_market_goal.assert_called_once_with( product_id=1, country_id=1, account_type='vendor', account_id='25257', user_id='alw:12345') result_response = json.loads(result.data.decode('utf-8')) assert result.status_code == 200 assert sales_goals.delete_target_market_goal.called assert result_response == resp def test_handler_target_market_goal_delete_header_error( mocker, client, valid_post_header): """Test `DELETE /goals/{productId}/{countryId}`. Test handler for fail on invalid headers. """ product_id = 1 country_id = 1 resp = {'target_market_goal_id': 1} mocker.patch.object( sales_goals, 'delete_target_market_goal', return_value=response.Response( message=resp)) invalid_header = valid_post_header invalid_header[header.GRASS_ACCOUNT_TYPE] = 'foobar' result = client.post( '/goals/{product_id}/{country_id}'.format( product_id=product_id, country_id=country_id), headers=invalid_header) assert result.status_code == 400 sales_goals.delete_target_market_goal.assert_not_called() def test_handler_create_marketing_highlight_success( mocker, client, valid_post_header, ): """Test `POST /marketing_highlights/{projectId}` handler success state.""" test_request_body = {} mocker.patch.object( marketing_highlights, 'create_project_marketing_highlights', return_value=response.Response( message='yoink')) mocker.patch.object( ownership, 'check_project_ownership', return_value=response.Response( message=True)) result = client.post( '/marketing_highlights/23234', headers=valid_post_header, data=json.dumps(test_request_body)) marketing_highlights.\ create_project_marketing_highlights.assert_called_once_with( project_id=23234, data=test_request_body, ) assert result.status_code == 200 assert result.data.decode('utf-8') == 'yoink' def test_handler_create_marketing_highlight_no_project_access( mocker, client, valid_post_header, ): """Test `POST /marketing_highlights/{projectId}` handler success state.""" mocker.patch.object( ownership, 'check_project_ownership', return_value=response.Response( status=403)) result = client.post( '/marketing_highlights/23234', headers=valid_post_header, data=json.dumps({})) assert result.status_code == 403 def test_handler_upsert_marketing_highlight_success( mocker, client, valid_post_header, ): """Test `PUT /marketing_highlights/{projectId}` handler success state.""" test_request_body = {} mocker.patch.object( marketing_highlights, 'upsert_project_marketing_highlights', return_value=response.Response( message='yoink')) mocker.patch.object( ownership, 'check_project_ownership', return_value=response.Response( message=True)) result = client.put( '/marketing_highlights/23234', headers=valid_post_header, data=json.dumps(test_request_body)) marketing_highlights.\ upsert_project_marketing_highlights.assert_called_once_with( project_id=23234, data=test_request_body, ) assert result.status_code == 200 assert result.data.decode('utf-8') == 'yoink' def test_handler_upsert_marketing_highlight_no_project_access( mocker, client, valid_post_header, ): """Test `PUT /marketing_highlights/{projectId}` handler success state.""" mocker.patch.object( ownership, 'check_project_ownership', return_value=response.Response( status=403)) result = client.put( '/marketing_highlights/23234', headers=valid_post_header, data=json.dumps({})) assert result.status_code == 403 def test_handler_get_marketing_highlight_success( mocker, client, valid_get_header, ): """Test `POST /marketing_highlights/{projectId}` handler success state.""" mocker.patch.object( marketing_highlights, 'get_project_marketing_highlights', return_value=response.Response( message='yoink')) mocker.patch.object( ownership, 'check_project_ownership', return_value=response.Response( message=True)) result = client.get( '/marketing_highlights/23234', headers=valid_get_header) marketing_highlights.\ get_project_marketing_highlights.assert_called_once_with( project_id=23234 ) assert result.status_code == 200 assert result.data.decode('utf-8') == 'yoink' def test_handler_get_marketing_highlight_no_project_access( mocker, client, valid_get_header, ): """Test `POST /marketing_highlights/{projectId}` handler success state.""" mocker.patch.object( ownership, 'check_project_ownership', return_value=response.Response( status=403)) result = client.get( '/marketing_highlights/23234', headers=valid_get_header) assert result.status_code == 403 def test_handler_delete_marketing_highlight_success( mocker, client, valid_delete_header, ): """Test `DELETE /marketing_highlights/{projectId}/{territoryId}`.""" mocker.patch.object( marketing_highlights, 'delete_project_marketing_highlight', return_value=response.Response( message='yoink')) mocker.patch.object( ownership, 'check_project_ownership', return_value=response.Response( message=True)) result = client.delete( '/marketing_highlights/23234/1', headers=valid_delete_header) marketing_highlights.\ delete_project_marketing_highlight.assert_called_once_with( project_id=23234, territory_id=1, ) assert result.status_code == 200 assert result.data.decode('utf-8') == 'yoink' def test_handler_delete_marketing_highlight_no_project_access( mocker, client, valid_delete_header, ): """Test `DELETE /marketing_highlights/{projectId}/{territoryId}` fail.""" mocker.patch.object( ownership, 'check_project_ownership', return_value=response.Response( status=403)) result = client.delete( '/marketing_highlights/23234/1', headers=valid_delete_header) assert result.status_code == 403 def test_handler_get_digital_projections_success( mocker, client, valid_get_header, ): """Test `POST /marketing_highlights/{projectId}` handler success state.""" mocker.patch.object( digital_projections, 'get_digital_projections_by_product_id', return_value=response.Response( message='yoink')) mocker.patch.object( ownership, 'check_product_ownership', return_value=response.Response( message=True)) result = client.get( '/digital/23234', headers=valid_get_header) digital_projections.\ get_digital_projections_by_product_id.assert_called_once_with( 23234, 'oa:179' ) assert result.status_code == 200 assert result.data.decode('utf-8') == 'yoink' def test_handler_get_digital_projections_no_access( mocker, client, valid_get_header, ): """Test `POST /marketing_highlights/{projectId}` handler success state.""" mocker.patch.object( ownership, 'check_product_ownership', return_value=response.Response( status=403)) result = client.get( '/digital/23234', headers=valid_get_header) assert result.status_code == 403 def test_handler_dataload_digital_product_projections_success( mocker, client, valid_post_header, ): """Test `POST /digital/projections/dataloader` handler success state.""" product_ids = [1, 2, 3] expected_result = [{ 'internal_note': 'abc', 'product_id': 92949, 'projections': [ { 'priority': 'a', 'product_id': 92949, 'territory_id': 1 }, { 'priority': 'b', 'product_id': 92949, 'territory_id': 2 } ] }] mocker.patch.object( digital_projections, 'dataload_digital_product_projections', return_value=response.Response(message=expected_result)) result = client.post( '/digital/projections/dataloader', headers=valid_post_header, data=json.dumps(product_ids) ) digital_projections.\ dataload_digital_product_projections.assert_called_once_with( product_ids ) assert result.status_code == 200 assert result.data.decode('utf-8') == json.dumps(expected_result) def test_handler_dataload_digital_product_projections_validation_failure( client, valid_post_header, ): """Test `POST /digital/projections/dataloader` handler input validation.""" product_ids = ['invalid', 'input', 'data'] result = client.post( '/digital/projections/dataloader', headers=valid_post_header, data=json.dumps(product_ids) ) assert result.status_code == 400 def test_handler_put_digital_territory_projections_success( mocker, client, valid_post_header, ): """Test `PUT /marketing_highlights/{projectId}` handler success state.""" mocker.patch.object( digital_projections, 'set_marketing_priority_for_product', return_value=response.Response( message='yoink')) mocker.patch.object( ownership, 'check_product_ownership', return_value=response.Response( message=True)) result = client.put( '/digital/23234/projections', headers=valid_post_header, data=json.dumps({'a': 1}) ) digital_projections.\ set_marketing_priority_for_product.assert_called_once_with( 23234, {'a': 1}, 'alw:12345', delete=True, ) assert result.status_code == 200 assert result.data.decode('utf-8') == 'yoink' def test_handler_post_digital_territory_projections_success( mocker, client, valid_post_header, ): """Test `POST /marketing_highlights/{projectId}` handler success state.""" mocker.patch.object( digital_projections, 'set_marketing_priority_for_product', return_value=response.Response( message='yoink')) mocker.patch.object( ownership, 'check_product_ownership', return_value=response.Response( message=True)) result = client.post( '/digital/23234/projections', headers=valid_post_header, data=json.dumps({'a': 1}) ) digital_projections.\ set_marketing_priority_for_product.assert_called_once_with( 23234, {'a': 1}, 'alw:12345', delete=False, ) assert result.status_code == 200 assert result.data.decode('utf-8') == 'yoink' def test_handler_post_digital_territory_projections_no_access( mocker, client, valid_get_header, ): """Test `POST /marketing_highlights/{projectId}` handler success state.""" mocker.patch.object( ownership, 'check_product_ownership', return_value=response.Response( status=403)) result = client.post( '/digital/23234/projections', headers=valid_get_header, data=json.dumps({}) ) assert result.status_code == 403 def test_handler_delete_digital_territory_projections_success( mocker, client, valid_delete_header, ): """Test delete digital projection.""" mocker.patch.object( digital_projections, 'delete_territory_projection', return_value=response.Response( message='yoink')) mocker.patch.object( ownership, 'check_product_ownership', return_value=response.Response( message=True)) result = client.delete( '/digital/23234/projection/1', headers=valid_delete_header, ) digital_projections.\ delete_territory_projection.assert_called_once_with( 23234, 1, ) assert result.status_code == 200 assert result.data.decode('utf-8') == 'yoink' def test_handler_delete_digital_territory_projections_no_access( mocker, client, valid_delete_header, ): """Test delete digital projection no access.""" mocker.patch.object( ownership, 'check_product_ownership', return_value=response.Response( status=403)) result = client.delete( '/digital/23234/projection/1', headers=valid_delete_header, data=json.dumps({}) ) assert result.status_code == 403 @patch( 'sales_goals.handlers.marketing_program_info', return_value=MagicMock(name='create_marketing_program_info')) def test_create_marketing_program_info( mock_program_info_logic, client, valid_post_header): """Test create marketing program info endpoint.""" test_request_body = { 'product_id': 3452345, 'data': [ { 'marketing_highlights': 'highlights' } ] } result = client.post( '/marketing_program_info', headers=valid_post_header, data=json.dumps(test_request_body)) mock_program_info_logic.create_marketing_program_info.assert_called_with( [ { 'marketing_highlights': 'highlights' } ] ) assert result.status_code == 200 @patch( 'sales_goals.handlers.marketing_program_info', return_value=MagicMock( name='get_marketing_program_info')) def test_get_marketing_program_info( mock_program_info_logic, client, valid_get_header): """Test get marketing program info.""" entity_type = 'product' entity_id = 3452345 mock_program_info_logic.get_marketing_program_info.return_value = [ # noqa { 'subject': 'blah blah', 'description': 'blah blah', }, { 'subject': 'blah blah 2', 'description': 'blah blah 2', }, ] result = client.get( f'/marketing_program_info/{entity_type}/{entity_id}', headers=valid_get_header) mock_program_info_logic.get_marketing_program_info.assert_called_with( # noqa entity_type, entity_id ) assert result.status_code == 200 @patch( 'sales_goals.handlers.marketing_program_info', return_value=MagicMock( name='get_marketing_program_info')) def test_get_marketing_program_info_by_program( mock_program_info_logic, client, valid_get_header): """Test get marketing program info by program.""" entity_type = 'product' entity_id = 3452345 program_id = 15 mock_program_info_logic.get_marketing_program_info.return_value = [ # noqa { 'subject': 'blah blah', 'description': 'blah blah', }, { 'subject': 'blah blah 2', 'description': 'blah blah 2', }, ] result = client.get( f'/marketing_program_info/{entity_type}/{entity_id}/program/{program_id}', headers=valid_get_header) mock_program_info_logic.get_marketing_program_info.assert_called_with( # noqa entity_type, entity_id, program_id ) assert result.status_code == 200 @patch( 'sales_goals.handlers.marketing_program_info', return_value=MagicMock( name='get_marketing_program_info')) def test_get_product_marketing_program_info_by_program( mock_program_info_logic, client, valid_get_header): """Test get product marketing program info by program endpoint.""" product_id = 3452345 program_id = 15 mock_program_info_logic.get_marketing_program_info.return_value = [ # noqa { 'subject': 'blah blah', 'description': 'blah blah', }, { 'subject': 'blah blah 2', 'description': 'blah blah 2', }, ] result = client.get( f'/marketing_program_info/{product_id}/{program_id}', headers=valid_get_header) mock_program_info_logic.get_marketing_program_info.assert_called_with( # noqa 'product', product_id, program_id ) assert result.status_code == 200 @patch( 'sales_goals.handlers.marketing_program_info', return_value=MagicMock(name='update_marketing_program_info')) def test_update_marketing_program_info( mock_program_info_logic, client, valid_post_header): """Test update marketing program info endpoint.""" test_request_body = { 'info_for_id': 3452345, 'info_for': 'release', 'description': 'blah blah blah', 'subject': 'blah blah', 'client': 'oa', 'mkt_program_id': 15, } result = client.put( '/marketing_program_info/234234', headers=valid_post_header, data=json.dumps(test_request_body)) mock_program_info_logic.update_marketing_program_info.assert_called_with( 234234, test_request_body ) assert result.status_code == 200 @patch( 'sales_goals.handlers.marketing_program_info', return_value=MagicMock(name='upsert_marketing_program_info')) def test_upsert_marketing_program_info( mock_program_info_logic, client, valid_post_header): """Test upsert marketing program info endpoint.""" product_id = 3452345 test_request_body = [{ 'info_for_id': product_id, 'info_for': 'release', 'description': 'blah blah blah', 'subject': 'blah blah', 'client': 'oa', 'mkt_program_id': 15, }] mock_program_info_logic.upsert_marketing_program_info.return_value = test_request_body result = client.put( f'/marketing_program_info/product/{product_id}', headers=valid_post_header, data=json.dumps(test_request_body)) mock_program_info_logic.upsert_marketing_program_info.assert_called_with( 'product', product_id, test_request_body ) assert result.status_code == 200 def test_handler_put_project_territory_projections_success( mocker, client, valid_post_header, ): """Test `PUT /marketing_highlights/{projectId}` handler success state.""" mocker.patch.object( digital_projections, 'upsert_project_territory_projections', return_value=response.Response( message='test')) mocker.patch.object( ownership, 'check_project_ownership', return_value=response.Response( message=True)) result = client.put( '/project/23234/projections', headers=valid_post_header, data=json.dumps({'a': 1}) ) digital_projections.\ upsert_project_territory_projections.assert_called_once_with( 23234, {'a': 1}, 'alw:12345', delete=True, ) assert result.status_code == 200 assert result.data.decode('utf-8') == 'test' def test_handler_post_project_territory_projections_success( mocker, client, valid_post_header, ): """Test `POST /marketing_highlights/{projectId}` handler success state.""" mocker.patch.object( digital_projections, 'upsert_project_territory_projections', return_value=response.Response( message='test')) mocker.patch.object( ownership, 'check_project_ownership', return_value=response.Response( message=True)) result = client.post( '/project/23234/projections', headers=valid_post_header, data=json.dumps({'a': 1}) ) digital_projections.\ upsert_project_territory_projections.assert_called_once_with( 23234, {'a': 1}, 'alw:12345', delete=False, ) assert result.status_code == 200 assert result.data.decode('utf-8') == 'test' def test_handler_get_project_marketing_projections_success( mocker, client, valid_get_header, ): """Test `GET /project/{projectId}` handler success state.""" mocker.patch.object( digital_projections, 'get_territory_priorities_for_project', return_value=response.Response( message='test')) mocker.patch.object( ownership, 'check_project_ownership', return_value=response.Response( message=True)) result = client.get( '/project/23234', headers=valid_get_header) digital_projections.\ get_territory_priorities_for_project.assert_called_once_with( 23234 ) assert result.status_code == 200 assert result.data.decode('utf-8') == 'test' def test_handler_dataload_project_marketing_projections_success( mocker, client, valid_post_header, ): """Test `POST /project/projections/dataloader` handler success state.""" project_ids = [1, 2, 3] expected_result = [{ 'internal_note': 'note 1', 'project_id': 1, 'projections': [ { 'priority': 'a', 'country_id': 1, 'project_id': 1 }, { 'priority': 'b', 'country_id': 2, 'project_id': 1 }, ], }] mocker.patch.object( digital_projections, 'dataload_project_marketing_priorities', return_value=response.Response(message=expected_result)) result = client.post( '/project/projections/dataloader', headers=valid_post_header, data=json.dumps(project_ids) ) digital_projections.\ dataload_project_marketing_priorities.assert_called_once_with( project_ids ) assert result.status_code == 200 assert result.data.decode('utf-8') == json.dumps(expected_result) def test_handler_dataload_project_marketing_projections_validation_failure( client, valid_post_header, ): """Test `POST /project/projections/dataloader` handler validates input.""" project_ids = ['invalid', 'input', 'data'] result = client.post( '/project/projections/dataloader', headers=valid_post_header, data=json.dumps(project_ids) ) assert result.status_code == 400 def test_handler_delete_project_territory_projections_success( mocker, client, valid_delete_header, ): """Test delete project marketing projection.""" mocker.patch.object( digital_projections, 'delete_project_territory_projection', return_value=response.Response( message='test')) mocker.patch.object( ownership, 'check_project_ownership', return_value=response.Response( message=True)) result = client.delete( '/project/23234/projection/1', headers=valid_delete_header, ) digital_projections.\ delete_project_territory_projection.assert_called_once_with( 23234, 1, ) assert result.status_code == 200 def test_upsert_project_global_projections_success( mocker, client, valid_post_header, ): """Test `POST /project/{projectId}` handler success state.""" mocker.patch.object( digital_projections, 'upsert_global_projections_for_project', return_value=response.Response( message='test')) mocker.patch.object( ownership, 'check_project_ownership', return_value=response.Response( message=True)) result = client.post( '/project/23234', headers=valid_post_header, data=json.dumps({'a': 1}) ) digital_projections.\ upsert_global_projections_for_project.assert_called_once_with( 23234, {'a': 1}, 'alw:12345' ) assert result.status_code == 200 assert result.data.decode('utf-8') == 'test'