"""Unit test for handlers.""" import copy import json from unittest.mock import MagicMock from flask import g from oto import response from owsrequest import context as owsrequest_context import pytest from project_manager import api, handlers from project_manager.constant import authorization from project_manager.constant import error_const from project_manager.constant import header_const from project_manager.constant import http_status_codes from project_manager.logic import label_copy_export from project_manager.logic import project_manager from project_manager.models import mkt_priority from project_manager.models import ows_product from project_manager.models import persister from project_manager.util import handler_util @pytest.mark.parametrize( ('header_account_type', 'header_account_id', 'account_type', 'account_id', 'expected_status_code'), [ # Non grass vendor ownership check success. (None, None, header_const.GRASS_ACCOUNT_TYPE_VENDOR, 1234, http_status_codes.OK), # Non grass subaccount ownership check success. (None, None, header_const.GRASS_ACCOUNT_TYPE_SUBACCOUNT, 1234, http_status_codes.OK), # account_type not "vendor" or "subaccount" error. (None, None, 'applesauce', None, http_status_codes.BAD_REQUEST), # account_id == 0. (None, None, header_const.GRASS_ACCOUNT_TYPE_VENDOR, 0, http_status_codes.BAD_REQUEST), # Partial grass headers error. (header_const.GRASS_ACCOUNT_TYPE_VENDOR, None, header_const.GRASS_ACCOUNT_TYPE_VENDOR, None, http_status_codes.BAD_REQUEST), # Grass vendor_id mismatch, vendor ownership check error. (header_const.GRASS_ACCOUNT_TYPE_VENDOR, '6789', header_const.GRASS_ACCOUNT_TYPE_VENDOR, 1234, http_status_codes.FORBIDDEN), # Grass vendor match, vendor ownership check success. (header_const.GRASS_ACCOUNT_TYPE_VENDOR, '6789', header_const.GRASS_ACCOUNT_TYPE_VENDOR, 6789, http_status_codes.OK), # Grass account_type subaccount, vendor ownership check error. (header_const.GRASS_ACCOUNT_TYPE_SUBACCOUNT, '6789', header_const.GRASS_ACCOUNT_TYPE_VENDOR, 1234, http_status_codes.FORBIDDEN), # Grass subaccount_id mismatch, subaccount ownership check error. (header_const.GRASS_ACCOUNT_TYPE_SUBACCOUNT, '6789', header_const.GRASS_ACCOUNT_TYPE_SUBACCOUNT, 1234, http_status_codes.FORBIDDEN), # Grass subaccount match, subaccount ownership check success. (header_const.GRASS_ACCOUNT_TYPE_SUBACCOUNT, '6789', header_const.GRASS_ACCOUNT_TYPE_SUBACCOUNT, 6789, http_status_codes.OK) ]) def test_handler_check_project_ownership_with_logic_success( header_account_type, header_account_id, account_type, account_id, expected_status_code, test_request_context, mocker): """Test HEAD call to ownership route with logic success.""" if account_type == header_const.GRASS_ACCOUNT_TYPE_VENDOR: vendor_and_subaccount = (account_id, None) else: vendor_and_subaccount = (None, account_id) mocker.patch.object( project_manager, 'check_project_ownership', return_value=response.Response( status=http_status_codes.OK, message=vendor_and_subaccount), autospec=True) headers = {} if header_account_type: headers[header_const.GRASS_ACCOUNT_TYPE] = header_account_type if header_account_id: headers[header_const.GRASS_ACCOUNT_ID] = header_account_id with api.app.test_request_context(headers=headers): ownership_response = handlers.check_project_ownership( account_type, account_id, 28) assert ownership_response.status_code == expected_status_code @pytest.mark.parametrize( ('header_account_type', 'header_account_id', 'account_type', 'account_id', 'expected_status_code'), [ # Grass vendor match, project does not exist, ownership check failure. (header_const.GRASS_ACCOUNT_TYPE_VENDOR, '6789', header_const.GRASS_ACCOUNT_TYPE_VENDOR, 6789, http_status_codes.NOT_FOUND), # Grass vendor match, project does not exist, ownership check failure. (header_const.GRASS_ACCOUNT_TYPE_SUBACCOUNT, '6789', header_const.GRASS_ACCOUNT_TYPE_SUBACCOUNT, 6789, http_status_codes.NOT_FOUND) ]) def test_handler_check_project_ownership_with_logic_failure( header_account_type, header_account_id, account_type, account_id, expected_status_code, test_request_context, mocker): """Test HEAD call to ownership route with logic failure.""" mocker.patch.object( project_manager, 'check_project_ownership', return_value=response.Response( status=http_status_codes.NOT_FOUND, message='Unable to find project_id 28'), autospec=True) headers = { header_const.GRASS_ACCOUNT_TYPE: header_account_type, header_const.GRASS_ACCOUNT_ID: header_account_id, } with api.app.test_request_context(headers=headers): ownership_response = handlers.check_project_ownership( account_type, account_id, 28) assert ownership_response.status_code == expected_status_code @pytest.mark.parametrize(('project_vendor_id', 'expected_status_code'), [ (1234, http_status_codes.OK), (2345, http_status_codes.FORBIDDEN)]) def test_handler_check_project_ownership_vendor_for_subaccount( project_vendor_id, expected_status_code, test_request_context, mocker): """Test /ownership/{account_type}/{account_id}/project/{project_id}. Vendor checking subaccount's project ownership. """ vendor_id = 1234 project_subaccount_id = 6789 mocker.patch.object( project_manager, 'check_project_ownership', return_value=response.Response( status=http_status_codes.OK, message=(project_vendor_id, project_subaccount_id)), autospec=True) headers = { header_const.GRASS_ACCOUNT_TYPE: header_const.GRASS_ACCOUNT_TYPE_VENDOR, header_const.GRASS_ACCOUNT_ID: str(vendor_id)} with api.app.test_request_context(headers=headers): ownership_response = handlers.check_project_ownership( header_const.GRASS_ACCOUNT_TYPE_SUBACCOUNT, project_subaccount_id, 28) assert ownership_response.status_code == expected_status_code def test_handler_check_project_ownership_with_logic_error( test_request_context, mocker): """Test HEAD call to ownership route with logic error.""" status_code = 987654 mocker.patch.object( project_manager, 'check_project_ownership', return_value=response.Response( status=status_code, message=(4568, 0)), autospec=True) ownership_response = handlers.check_project_ownership( header_const.GRASS_ACCOUNT_TYPE_VENDOR, 1234, 28) assert ownership_response.status_code == status_code def test_handler_get_project_success(test_request_context, header, mocker): """Test GET project handler success state.""" expected_message = {'test': 'test message'} project_id = "doesn't matter for this test" mocker.patch.object( project_manager, 'get_project', return_value=response.Response(expected_message)) with api.app.test_request_context(headers=header): handler_response = handlers.get_project(project_id) project_manager.get_project.assert_called_once_with( header[header_const.GRASS_ACCOUNT_TYPE], header[header_const.GRASS_ACCOUNT_ID], project_id, False ) assert handler_response.status_code == 200 content_type = handler_response.headers[header_const.CONTENT_TYPE] assert content_type == header_const.APPLICATION_JSON response_message = json.loads(handler_response.data.decode()) assert response_message == expected_message def test_handler_get_project_deleted(test_request_context, header, mocker): """Test GET project handler success state.""" expected_message = {'test': 'test message'} project_id = 1234 mocker.patch.object( project_manager, 'get_project', return_value=response.Response(expected_message)) with api.app.test_request_context('?include_deletions=True', headers=header): handler_response = handlers.get_project(project_id) project_manager.get_project.assert_called_once_with( header[header_const.GRASS_ACCOUNT_TYPE], header[header_const.GRASS_ACCOUNT_ID], project_id, True ) assert handler_response.status_code == 200 content_type = handler_response.headers[header_const.CONTENT_TYPE] assert content_type == header_const.APPLICATION_JSON response_message = json.loads(handler_response.data.decode()) assert response_message == expected_message def test_handler_get_project_by_project_code_oa_user( test_request_context, mocker): """Test GET get_project by parameter.""" with api.app.test_request_context( '?project_code=ABC&account_id=7123&subaccount_id=1', headers={ header_const.ORCHARD_USER_ID: 'oa:123', header_const.CONTENT_TYPE: header_const.APPLICATION_JSON} ): expected_message = {'test': 'test message'} project_code = 'ABC' mocker.patch.object( project_manager, 'get_project_by_project_code', return_value=response.Response(expected_message)) handler_response = handlers.get_project_by_parameter() project_manager.get_project_by_project_code.assert_called_once_with( 7123, 1, project_code) assert handler_response.status_code == 200 content_type = handler_response.headers[header_const.CONTENT_TYPE] assert content_type == header_const.APPLICATION_JSON response_message = json.loads(handler_response.data.decode()) assert response_message == expected_message def test_handler_get_project_by_project_code_not_oa_user(header, mocker): """Test GET get_project by parameter.""" with api.app.test_request_context( '?project_code=ABC&account_id=7123&subaccount_id=1', headers={ header_const.ORCHARD_USER_ID: 'alw:123', header_const.CONTENT_TYPE: header_const.APPLICATION_JSON}): expected_message = {'test': 'test message'} mocker.patch.object( project_manager, 'get_project_by_project_code', return_value=response.Response(expected_message)) handler_response = handlers.get_project_by_parameter() project_manager.get_project_by_project_code.assert_not_called() assert handler_response.status_code == 403 def test_handler_get_project_by_project_code_missing_project_code( header, mocker): """Test GET get_project by parameter with missing param.""" with api.app.test_request_context( '?account_id=7123&subaccount_id=1', headers=header): expected_message = { error_const.ERROR_CODE: error_const.VALIDATION_ERROR, error_const.ERROR_DETAIL: 'No project_code provided'} mocker.patch.object( project_manager, 'get_project_by_project_code', return_value=response.Response(expected_message)) handler_response = handlers.get_project_by_parameter() project_manager.get_project_by_project_code.assert_not_called() assert handler_response.status_code == 400 content_type = handler_response.headers[header_const.CONTENT_TYPE] assert content_type == header_const.APPLICATION_JSON response_message = json.loads(handler_response.data.decode()) assert response_message == expected_message def test_handler_get_project_by_project_code_missing_account_and_subaccount( header, mocker): """Test GET get_project by parameter with missing param.""" with api.app.test_request_context( '?project_code=ABC', headers=header): expected_message = { error_const.ERROR_CODE: error_const.VALIDATION_ERROR, error_const.ERROR_DETAIL: 'No account_id or subaccount_id provided' } mocker.patch.object( project_manager, 'get_project_by_project_code', return_value=response.Response(expected_message)) handler_response = handlers.get_project_by_parameter() project_manager.get_project_by_project_code.assert_not_called() assert handler_response.status_code == 400 content_type = handler_response.headers[header_const.CONTENT_TYPE] assert content_type == header_const.APPLICATION_JSON response_message = json.loads(handler_response.data.decode()) assert response_message == expected_message def test_handler_get_project_bad_grass_headers(header, mocker): """Test GET project handler missing grass account id returns error.""" with api.app.test_request_context(headers=header): mutated_header = copy.copy(header) mutated_header.pop(header_const.GRASS_ACCOUNT_ID) mocker.patch.object( handler_util, 'access_check', return_value=response.create_error_response( error_const.AUTHORIZATION_ERROR, 'Authorization error', status=403)) project_id = 'doesn’t matter for this test' g.log = MagicMock(return_value='info') mocker.spy(project_manager, 'get_project') handler_response = handlers.get_project(project_id) handler_message = json.loads(handler_response.data.decode()) assert not project_manager.get_project.called assert not g.log.info.called assert handler_response.status_code == 403 assert handler_message.get('code') == error_const.AUTHORIZATION_ERROR assert handler_message.get('message') == 'Authorization error' def test_handler_get_project_codes_available_for_use_success( test_request_context, header, mocker): """Test GET get_project by parameter.""" with api.app.test_request_context( headers=header, json={ 'project_codes': ['ABC', 'DEF', 'GHI'], 'account_uuid': 7123, 'subaccount_uuid': 1, } ): expected_message = { 'available_project_codes': ['ABC', 'DEF'], 'existing_projects': [ { 'product_id': 123, 'project_code': 'GHI', 'project_name': 'Test project', 'artist_name': 'Test name', } ] } project_codes = ['ABC', 'DEF', 'GHI'] mocker.patch.object( project_manager, 'get_available_project_codes', return_value=response.Response(expected_message)) handler_response = handlers.get_project_codes_available_for_use() project_manager.get_available_project_codes.assert_called_once_with( 7123, 1, project_codes) assert handler_response.status_code == 200 content_type = handler_response.headers[header_const.CONTENT_TYPE] assert content_type == header_const.APPLICATION_JSON response_message = json.loads(handler_response.data.decode()) assert response_message == expected_message @pytest.mark.parametrize( ('account_type'), [ (header_const.GRASS_ACCOUNT_TYPE_SUBACCOUNT), (header_const.GRASS_ACCOUNT_TYPE_VENDOR) ]) def test_get_product_imprints(account_type, mocker): """Assert expected response is returned.""" account_id = 123 request_headers = { header_const.GRASS_ACCOUNT_TYPE: account_type, header_const.GRASS_ACCOUNT_ID: account_id, } with api.app.test_request_context(headers=request_headers): expected_message = {'test': 'test message'} project_id = "doesn't matter for this test" mocker.patch.object( project_manager, 'get_product_imprints', return_value=response.Response(expected_message), autospec=True) handler_response = handlers.get_product_imprints(project_id) project_manager.get_product_imprints.assert_called_once_with( project_id, account_type, account_id) assert handler_response.status_code == 200 content_type = handler_response.headers[header_const.CONTENT_TYPE] assert content_type == header_const.APPLICATION_JSON response_message = json.loads(handler_response.data.decode()) assert response_message == expected_message def test_get_product_imprints_with_no_grass_headers( test_request_context, mocker): """Assert expected response is returned.""" expected_message = {'test': 'test message'} project_id = "doesn't matter for this test" mocker.patch.object( project_manager, 'get_product_imprints', return_value=response.Response(expected_message), autospec=True) handler_response = handlers.get_product_imprints(project_id) project_manager.get_product_imprints.assert_called_once_with( project_id, None, None) assert handler_response.status_code == 200 content_type = handler_response.headers[header_const.CONTENT_TYPE] assert content_type == header_const.APPLICATION_JSON response_message = json.loads(handler_response.data.decode()) assert response_message == expected_message @pytest.mark.parametrize( ('request_headers'), [ # missing header_const.GRASS_ACCOUNT_ID header ({header_const.GRASS_ACCOUNT_TYPE: header_const.GRASS_ACCOUNT_TYPE_SUBACCOUNT}), ({header_const.GRASS_ACCOUNT_TYPE: header_const.GRASS_ACCOUNT_TYPE_VENDOR}), # missing header_const.GRASS_ACCOUNT_TYPE header ({header_const.GRASS_ACCOUNT_ID: 1}) ]) def test_get_product_imprints_with_partial_grass_headers( request_headers, mocker): """Assert expected response is returned.""" with api.app.test_request_context(headers=request_headers): expected_message = { 'code': 'authorization_error', 'message': 'Authorization error'} project_id = "doesn't matter for this test" mocker.patch.object( project_manager, 'get_product_imprints', return_value=response.Response(expected_message), autospec=True) handler_response = handlers.get_product_imprints(project_id) assert not project_manager.get_product_imprints.called assert handler_response.status_code == 403 content_type = handler_response.headers[header_const.CONTENT_TYPE] assert content_type == header_const.APPLICATION_JSON response_message = json.loads(handler_response.data.decode()) assert response_message == expected_message def test_get_product_subgenres(header, mocker): """Assert expected response is returned.""" with api.app.test_request_context(headers=header): expected_message = {'test': 'test message'} genre_id = "doesn't matter for this test" mocker.patch.object( project_manager, 'get_product_subgenres', return_value=response.Response(expected_message)) handler_response = handlers.get_product_subgenres(genre_id) project_manager.get_product_subgenres.assert_called_once_with(genre_id) assert handler_response.status_code == 200 content_type = handler_response.headers[header_const.CONTENT_TYPE] assert content_type == header_const.APPLICATION_JSON response_message = json.loads(handler_response.data.decode()) assert response_message == expected_message def test_get_public_product_subgenres(header, mocker): """Assert expected response is returned.""" with api.app.test_request_context(headers=header): expected_message = {'test': 'test message'} genre_id = "doesn't matter for this test" mocker.patch.object( project_manager, 'get_product_subgenres', return_value=response.Response(expected_message)) handler_response = handlers.get_public_product_subgenres(genre_id) project_manager.get_product_subgenres\ .assert_called_once_with(genre_id) assert handler_response.status_code == 200 assert handler_response.headers['Cache-Control'] == 'max-age=3600' content_type = handler_response.headers[header_const.CONTENT_TYPE] assert content_type == header_const.APPLICATION_JSON response_message = json.loads(handler_response.data.decode()) assert response_message == expected_message def test_get_product_types(header, mocker): """Assert expected response is returned.""" with api.app.test_request_context(headers=header): expected_message = {'test': 'test message'} mocker.patch.object( project_manager, 'get_product_types', return_value=response.Response(expected_message)) handler_response = handlers.get_product_types() assert handler_response.status_code == 200 content_type = handler_response.headers[header_const.CONTENT_TYPE] assert content_type == header_const.APPLICATION_JSON response_message = json.loads(handler_response.data.decode()) assert response_message == expected_message def test_get_product_genres(mocker, header): """Product genres returned.""" with api.app.test_request_context(headers=header): expected_message = {'test': 'test message'} mocker.patch.object( project_manager, 'get_product_genres', return_value=response.Response(expected_message)) handler_response = handlers.get_product_genres() response_message = json.loads(handler_response.data.decode()) assert handler_response.status_code == 200 assert response_message == expected_message def test_get_public_product_genres(mocker, header): """Product genres returned.""" with api.app.test_request_context(headers=header): expected_message = {'test': 'test message'} mocker.patch.object( project_manager, 'get_product_genres', return_value=response.Response(expected_message)) handler_response = handlers.get_public_product_genres() response_message = json.loads(handler_response.data.decode()) assert handler_response.status_code == 200 assert handler_response.headers['Cache-Control'] == 'max-age=3600' assert response_message == expected_message def test_post_project_handler( client, header, monkeypatch, get_valid_post_dict): """Test posting a project successfully.""" monkeypatch.setattr(project_manager, 'add_project', MagicMock( return_value=response.Response(status=201))) res = client.post( '/project', headers=header, data=json.dumps(get_valid_post_dict)) assert res.status_code == 201 def test_post_project_handler_with_user( client, header_user, monkeypatch, get_valid_post_dict): """Test posting a project successfully.""" monkeypatch.setattr(project_manager, 'add_project', MagicMock( return_value=response.Response(status=201))) res = client.post( '/project', headers=header_user, data=json.dumps(get_valid_post_dict)) assert res.status_code == 201 def test_post_project_handler_bad_header( client, header, monkeypatch, get_valid_post_dict): """Test posting a project with bad header.""" monkeypatch.setattr(project_manager, 'add_project', MagicMock( return_value=response.Response(status=201))) res = client.post( '/project', headers=None, data=json.dumps(get_valid_post_dict)) assert res.status_code == 400 project_manager.add_project.assert_not_called() def test_update_project_handler(client, header, monkeypatch): """Test updating a project successfully.""" monkeypatch.setattr(project_manager, 'update_project', MagicMock( return_value=response.Response())) monkeypatch.setattr( ows_product, 'update_products_by_pool', MagicMock(return_value=response.Response( status=200, message={'message': 'ok', 'status': 200}))) res = client.put( '/project/0', headers=header, data=json.dumps({})) assert res.status_code == 200 update_params = ['vendor', 7123, 0, {}, None] project_manager.update_project.assert_called_once_with( *update_params) def test_update_project_handler_with_user(client, header_user, monkeypatch): """Test updating a project successfully.""" monkeypatch.setattr(project_manager, 'update_project', MagicMock( return_value=response.Response())) monkeypatch.setattr( ows_product, 'update_products_by_pool', MagicMock(return_value=response.Response( status=200, message={'message': 'ok', 'status': 200}))) res = client.put('/project/0', headers=header_user, data=json.dumps({})) user = header_user['Orchard-User-Id'] assert res.status_code == 200 update_params = ['subaccount', 1, 0, {}, user] project_manager.update_project.assert_called_once_with( *update_params) def test_update_project_handler_as_oa(client, header_user_oa, monkeypatch): """Test updating a project as an Orchard Admin.""" monkeypatch.setattr(project_manager, 'update_project', MagicMock( return_value=response.Response())) monkeypatch.setattr( ows_product, 'update_products_by_pool', MagicMock(return_value=response.Response( status=200, message={'message': 'ok', 'status': 200}))) res = client.put('/project/0', headers=header_user_oa, data=json.dumps({})) user = header_user_oa['Orchard-User-Id'] assert res.status_code == 200 update_params = [None, None, 0, {}, user] project_manager.update_project.assert_called_once_with(*update_params) def test_update_project_handler_does_not_need_grass( client, header, monkeypatch): """Test updating a project successfully.""" monkeypatch.setattr(project_manager, 'update_project', MagicMock( return_value=response.Response())) header_without_grass = header.copy() header_without_grass.pop('Grass-Account-Id') header_without_grass.pop('Grass-Account-Type') monkeypatch.setattr( ows_product, 'update_products_by_pool', MagicMock(return_value=response.Response( status=200, message={'message': 'ok', 'status': 200}))) res = client.put( '/project/0', headers=header_without_grass, data=json.dumps({})) assert res.status_code == 200 project_manager.update_project.assert_called_once_with( None, None, 0, {}, None) def test_update_project_handler_bad_header(client, monkeypatch): """Test updating a project using with bad header.""" monkeypatch.setattr(project_manager, 'update_project', MagicMock( return_value=response.Response())) res = client.put( '/project/0', headers=None, data=json.dumps({})) assert res.status_code == 400 project_manager.update_project.assert_not_called() def test_get_products_for_project_handler(header, mocker): """Test get_products_for_project route.""" with api.app.test_request_context(headers=header): expected_message = {'test': 'test message'} project_id = "doesn't matter for this test" mocker.patch.object( project_manager, 'get_products_for_project', return_value=response.Response(expected_message)) handler_response = handlers.get_products_for_project(project_id) project_manager.get_products_for_project.assert_called_once_with( header[header_const.GRASS_ACCOUNT_TYPE], header[header_const.GRASS_ACCOUNT_ID], project_id, ) assert handler_response.status_code == 200 content_type = handler_response.headers[header_const.CONTENT_TYPE] assert content_type == header_const.APPLICATION_JSON response_message = json.loads(handler_response.data.decode()) assert response_message == expected_message def test_get_one_product_for_project(client, monkeypatch, header): """Test get_products_for_project route.""" with api.app.test_request_context(headers=header): monkeypatch.setattr( project_manager, 'get_product_for_project', MagicMock( return_value=response.Response())) res = client.get('/project/1/product/1', headers=header) params = ['vendor', 7123, 1, 1] assert res.status_code == 200 project_manager.get_product_for_project.assert_called_once_with( *params) def test_get_projects(client, monkeypatch, header): """Test get_products_for_project route.""" monkeypatch.setattr(project_manager, 'get_projects', MagicMock( return_value=response.Response())) res = client.get('/projects', headers=header) params = ['7123', None, 0, 50] assert res.status_code == 200 project_manager.get_projects.assert_called_once_with(*params) def test_get_projects_subaccount(client, monkeypatch, header_subaccount): """Test get_products_for_project route.""" monkeypatch.setattr(project_manager, 'get_projects', MagicMock( return_value=response.Response())) res = client.get('/projects', headers=header_subaccount) params = [None, '1', 0, 50] assert res.status_code == 200 project_manager.get_projects.assert_called_once_with(*params) def test_get_projects_bad_header(client, monkeypatch): """Test get_products_for_project route.""" monkeypatch.setattr(project_manager, 'get_projects', MagicMock( return_value=response.Response())) res = client.get('/projects', headers=None) assert res.status_code == 400 project_manager.get_projects.assert_not_called() def test_get_projects_page_limit_exceeded(client, monkeypatch, header): """Test get_products_for_project route.""" monkeypatch.setattr(project_manager, 'get_projects', MagicMock( return_value=response.Response())) res = client.get('/projects?page_limit=5001', headers=header) assert res.status_code == 400 project_manager.get_projects.assert_not_called() def test_internal_error_handler(): """Test response given when errors raised.""" res = handlers.internal_server_error(None) res_message = json.loads(res.data.decode()) assert res.status_code == 500 assert res_message.get('message') == 'Internal Server Error' def test_handle_sqlalchemy_error(test_request_context): """Test handling of sqlalchemy error.""" res = handlers.handle_sqlalchemy_error(None) assert res.status_code == 500 def test_page_not_found(client): """Test response when client request not found.""" res = client.get('/projectasaurous') assert res.status_code == 404 @pytest.mark.parametrize('generation_response', (200, 403)) def test_post_report_handler( client, header, monkeypatch, generation_response): """Test posting report generation successfully.""" project_id = 123 monkeypatch.setattr( label_copy_export, 'trigger_project_metadata_generation', MagicMock( return_value=response.Response(status=generation_response))) res = client.post( '/report/{project_id}'.format( project_id=project_id), headers=header) assert res.status_code == generation_response def test_get_report_handler_success( client, header, monkeypatch): """Test get metadata report handler success.""" project_id = 123 message = { 'download_url': '/some/url', 'timestamp': '02-11-2015'} mock_res = response.Response( status=200, message=message) monkeypatch.setattr( label_copy_export, 'get_generated_metadata_for_project', MagicMock( return_value=mock_res)) res = client.get( '/report/{project_id}'.format( project_id=project_id), headers=header) assert res.status_code == 200 assert json.loads(res.data.decode()) == message def test_get_report_handler_headers_validation_failed( client, header, monkeypatch): """Test get metadata report handler access check failed.""" project_id = 123 monkeypatch.setattr(handler_util, 'access_check', MagicMock( return_value=response.Response(status=403))) monkeypatch.setattr( label_copy_export, 'get_generated_metadata_for_project', MagicMock( return_value=response.Response(status=200))) res = client.get( '/report/{project_id}'.format( project_id=project_id), headers=header) assert res.status_code == 403 label_copy_export.get_generated_metadata_for_project.assert_not_called() def test_get_report_handler_headers_get_metadata_failed( client, header, monkeypatch): """Test get metadata report handler failed.""" project_id = 123 monkeypatch.setattr( label_copy_export, 'get_generated_metadata_for_project', MagicMock( return_value=response.Response(status=404))) res = client.get( '/report/{project_id}'.format( project_id=project_id), headers=header) assert res.status_code == 404 def test_delete_project_success(client, header, mocker, monkeypatch): """Test deleting a project success.""" proj_id = 123 mocker.patch.object( project_manager, 'delete_project', return_value=response.Response()) result = client.delete('/project/{}'.format(proj_id), headers=header) assert result.status_code == 200 project_manager.delete_project.assert_called_with(proj_id, 'vendor', 7123) def test_delete_project_error_response(client, mocker, header, monkeypatch): """Test deleting a project when some error occurs.""" proj_id = 123 mock_error_response = response.create_fatal_response() mocker.patch.object( project_manager, 'delete_project', return_value=mock_error_response) result = client.delete('/project/{}'.format(proj_id), headers=header) assert result.status_code == 500 project_manager.delete_project.assert_called_with(proj_id, 'vendor', 7123) def test_hard_delete_project_success(client, header, mocker, monkeypatch): """Test hard deleting a project success.""" header_context_mock = MagicMock() header_context_mock.jwt_identity_id =\ authorization.HARD_DELETE_PROJECT_AUTHORIZED_IDENTITIES[0] mocker.patch.object( owsrequest_context, 'get_request_context_from_headers', return_value=header_context_mock ) proj_id = 123 mocker.patch.object( project_manager, 'delete_project', return_value=response.Response()) result = client.delete( '/project/{}/hard-delete'.format(proj_id), headers=header, ) assert result.status_code == 200 project_manager.delete_project.assert_called_with( project_id=proj_id, account_type=None, account_id=None, hard_delete=True ) def test_get_project_document_with_headers(client, header, mocker): """Test error when passing grass headers.""" project_id = 123 res = client.get( '/project/{project_id}/document'.format( project_id=project_id), headers=header) assert res.status_code == 500 def test_get_project_document_success(client, header, mocker): """Test error when passing grass headers.""" project_id = 123 mocker.patch.object( persister, 'get_project_and_artist_info_by_id', return_value=response.Response()) res = client.get( '/project/{project_id}/document'.format( project_id=project_id)) assert res.status_code == 200 persister.get_project_and_artist_info_by_id.assert_called_once_with( project_id, False) def test_get_project_document_with_tenant_uuids(client, header, mocker): """Test error when passing grass headers.""" project_id = 123 mocker.patch.object( persister, 'get_project_and_artist_info_by_id', return_value=response.Response()) res = client.get('/project/{project_id}/document?with_tenant_uuids=1'.format( project_id=project_id)) assert res.status_code == 200 persister.get_project_and_artist_info_by_id.assert_called_once_with( project_id, True) def test_set_mkt_priority_for_project(client, header_user_oa, monkeypatch): """Test setting a project marketing priority.""" project_id = 1 country_id = 1 priority = 'a' mkt_id = 12 mkt_priority_obj = [{ 'id': mkt_id, 'project_id': project_id, 'country_id': country_id, 'priority': priority }] monkeypatch.setattr(project_manager, 'set_mkt_priority', MagicMock( return_value=response.Response(mkt_priority_obj))) monkeypatch.setattr( mkt_priority, 'set_mkt_priority_by_project_id', MagicMock(return_value=response.Response( status=200, message=mkt_priority_obj[0]))) res = client.post( '/project/1/mkt_priority', headers=header_user_oa, data=json.dumps(mkt_priority_obj[0]) ) assert res.status_code == 200 update_params = [project_id, country_id, priority, 123] project_manager.set_mkt_priority.assert_called_once_with(*update_params) def test_get_mkt_priority_for_project(client, header_user_oa, monkeypatch): """Test getting a project marketing priority.""" project_id = 1 country_id = 1 priority = 'a' mkt_id = 12 mkt_priority_obj = [{ 'id': mkt_id, 'project_id': project_id, 'country_id': country_id, 'priority': priority }] monkeypatch.setattr(project_manager, 'get_mkt_priority', MagicMock( return_value=response.Response(mkt_priority_obj))) monkeypatch.setattr( mkt_priority, 'get_mkt_priority_by_project_id', MagicMock(return_value=response.Response( status=200, message=mkt_priority_obj))) res = client.get('/project/1/mkt_priority', headers=header_user_oa) assert res.status_code == 200 project_manager.get_mkt_priority.assert_called_once_with(project_id) def test_dataload_mkt_priority(client, header_user_oa, monkeypatch): """Test dataloading project marketing priorities.""" project_ids = [1, 2, 3] country_id = 1 priority = 'a' mkt_id = 12 mkt_priority_obj = [ { 'id': mkt_id, 'project_id': 1, 'country_id': country_id, 'priority': priority }, { 'id': mkt_id + 1, 'project_id': 2, 'country_id': country_id + 1, 'priority': priority }, { 'id': mkt_id + 1, 'project_id': 3, 'country_id': country_id + 1, 'priority': priority }, ] monkeypatch.setattr(project_manager, 'get_bulk_mkt_priority', MagicMock( return_value=response.Response(mkt_priority_obj))) res = client.post( '/project/mkt_priority/dataloader', headers=header_user_oa, data=json.dumps(project_ids), ) assert res.status_code == 200 project_manager.get_bulk_mkt_priority.assert_called_once_with(project_ids) def test_dataload_mkt_priority_no_data(client, header_user_oa, monkeypatch): """Test dataloading project marketing priorities returns no data.""" project_ids = [123, 456, 789] mkt_priority_obj = [] monkeypatch.setattr(project_manager, 'get_bulk_mkt_priority', MagicMock( return_value=response.Response(mkt_priority_obj))) res = client.post( '/project/mkt_priority/dataloader', headers=header_user_oa, data=json.dumps(project_ids), ) assert res.status_code == 200 project_manager.get_bulk_mkt_priority.assert_called_once_with(project_ids) def test_dataload_mkt_priority_validation(client, header_user_oa): """Test dataloading project marketing priorities validates payload.""" project_ids = ['invalid', 'input', 'data'] res = client.post( '/project/mkt_priority/dataloader', headers=header_user_oa, data=json.dumps(project_ids), ) assert res.status_code == 400 def test_dataload_projects(client, header, monkeypatch): """Test bulk-loading projects forwards the grass account context and ids.""" project_ids = [1, 2, 3] monkeypatch.setattr(project_manager, 'get_bulk_projects', MagicMock( return_value=response.Response({'projects': [None, None, None]}))) res = client.post( '/project/dataloader', headers=header, data=json.dumps(project_ids), ) assert res.status_code == 200 project_manager.get_bulk_projects.assert_called_once_with( header[header_const.GRASS_ACCOUNT_TYPE], int(header[header_const.GRASS_ACCOUNT_ID]), project_ids, ) def test_dataload_projects_internal_no_grass(client, header, monkeypatch): """Test bulk-loading projects with no grass headers (internal call).""" project_ids = [1, 2] monkeypatch.setattr(project_manager, 'get_bulk_projects', MagicMock( return_value=response.Response({'projects': [None, None]}))) header_without_grass = header.copy() header_without_grass.pop(header_const.GRASS_ACCOUNT_ID) header_without_grass.pop(header_const.GRASS_ACCOUNT_TYPE) res = client.post( '/project/dataloader', headers=header_without_grass, data=json.dumps(project_ids), ) assert res.status_code == 200 project_manager.get_bulk_projects.assert_called_once_with( None, None, project_ids) def test_dataload_projects_validation(client, header): """Test bulk-loading projects validates the payload.""" res = client.post( '/project/dataloader', headers=header, data=json.dumps(['not', 'ints']), ) assert res.status_code == 400 def test_delete_mkt_priority_for_project(client, header_user_oa, monkeypatch): """Test deleting a project marketing priority.""" project_id = 1 projection_id = 1 monkeypatch.setattr(project_manager, 'delete_mkt_priority', MagicMock( return_value=response.Response())) monkeypatch.setattr( mkt_priority, 'delete_mkt_priority_by_project_id', MagicMock(return_value=response.Response( status=200))) res = client.delete('/project/1/mkt_priority/1', headers=header_user_oa) assert res.status_code == 200 project_manager.delete_mkt_priority.assert_called_once_with(project_id, projection_id) def test_bulk_delete_mkt_priority_for_project(client, header_user_oa, monkeypatch): """Test delete all marketing priorities of a project.""" project_id = 1 monkeypatch.setattr(project_manager, 'bulk_delete_mkt_priority_for_project', MagicMock( return_value=response.Response())) monkeypatch.setattr( mkt_priority, 'bulk_delete_mkt_priority_for_project', MagicMock(return_value=response.Response( status=200))) res = client.delete('/project/1/mkt_priority', headers=header_user_oa) assert res.status_code == 200 project_manager.bulk_delete_mkt_priority_for_project.assert_called_once_with( project_id)