"""Tests for main handler /image base.""" import json from unittest.mock import MagicMock import pytest from flask.testing import FlaskClient from flexmock import flexmock from owsrequest.constants import headers as owsrequest_headers from owsresponse import response from pytest import MonkeyPatch from assets.exceptions import AssetUploadError from assets.logic import asset_copy, image_location, ownership from assets.logic.legacy import image_location as image_location_legacy OA_HEADERS = {"Orchard-User-Id": "oa:12345"} ALW_HEADERS = { "Orchard-User-Id": "alw:12345", "Grass-Account-Id": "234234", "Grass-Account-Type": "vendor", } def test_get_image_location_profile_user(fixture_client: FlaskClient) -> None: """Test get_image_location for identity logo with no headers.""" entity_id = "123456auth0" expected = {"code": "not_found_error", "message": "No image for user's identity."} request_url = f"/image/identity/logo/{entity_id}/location" result = fixture_client.get(request_url) result_message = json.loads(result.data.decode("utf8")) assert result.status_code == 404 assert result.headers.get("Correlation-Id") assert result_message == expected def test_get_image_location_invalid_headers(fixture_client: FlaskClient) -> None: """Test get_image_location for identity logo but with fake headers.""" entity_id = "123456auth0" headers = {"Orchard-Profile-Type": "ArtistProfile"} expected = { "code": "bad_request", "message": "invalid combination of profile_type, profile_id, and identity_id", } request_url = f"/image/identity/logo/{entity_id}/location" result = fixture_client.get(request_url, headers=headers) result_message = json.loads(result.data.decode("utf8")) assert result.status_code == 400 assert result.headers.get("Correlation-Id") assert result_message == expected def test_get_image_location_access_different_identity( fixture_client: FlaskClient, ) -> None: """Test get_image_location for identity logo but with fake headers.""" entity_id = "123456auth0" headers = { "Orchard-Profile-Type": "ArtistProfile", "Orchard-Profile-Id": 123, "Orchard-Identity-Id": "fake", } expected = {"code": "request_unauthorized", "message": "Request not allowed."} request_url = f"/image/identity/logo/{entity_id}/location" result = fixture_client.get(request_url, headers=headers) result_message = json.loads(result.data.decode("utf8")) assert result.status_code == 400 assert result.headers.get("Correlation-Id") assert result_message == expected def test_get_profile_image(fixture_client: FlaskClient) -> None: """Test route for getting the location of a profile image.""" mock_logic_response = "vendor/23423/2341234.jpg" profile_id = 68548 profile_type = "LabelProfile" headers = { owsrequest_headers.ORCHARD_PROFILE_ID: profile_id, owsrequest_headers.ORCHARD_PROFILE_TYPE: profile_type, } flexmock(image_location).should_receive("get_profile_image").with_args( str(profile_id), profile_type ).and_return(mock_logic_response) result = fixture_client.get("/image/profile", headers=headers) result_message = result.data.decode("utf8") assert result.status_code == 200 assert result.headers.get("Correlation-Id") assert mock_logic_response == result_message def test_get_image_location_v2(fixture_client: FlaskClient) -> None: """Test route for getting the location of an image file uses v2 logic.""" entity_id = 123456 mock_logic_response = "some_location" flexmock(image_location).should_receive("get_image_location").with_args( entity_id, "cover" ).and_return(mock_logic_response) request_url = "/image/{image_type}/{image_format}/{entity_id}/location".format( entity_id=entity_id, image_type="product", image_format="cover" ) result = fixture_client.get(request_url) result_message = result.data.decode("utf8") assert result.status_code == 200 assert result.headers.get("Correlation-Id") assert mock_logic_response == result_message def test_get_image_location_v2_correction_and_v2_submission_flag_on( fixture_client: FlaskClient, ) -> None: """Test route for getting the location of a correction image file falls back on v1 logic.""" entity_id = 123456 mock_logic_response = "some_location" flexmock(image_location).should_receive("get_image_location").with_args( entity_id, "cover_correction" ).and_return(mock_logic_response) request_url = "/image/{image_type}/{image_format}/{entity_id}/location".format( entity_id=entity_id, image_type="product", image_format="cover_correction" ) result = fixture_client.get(request_url) result_message = result.data.decode("utf8") assert result.status_code == 200 assert result.headers.get("Correlation-Id") assert mock_logic_response == result_message def test_get_image_location_v2_permission_failure(fixture_client: FlaskClient) -> None: """Test permission failure of route for getting v2 image location.""" # mocking entity_id = 123456 flexmock(ownership).should_receive("check_ownership").and_return( response.create_error_response( code="not_owned", message="not_owned", status=403 ) ) flexmock(image_location).should_receive("get_image_location").with_args( entity_id, "cover" ).and_return(response.Response()) # test function call request_url = "/image/{image_type}/{image_format}/{entity_id}/location".format( entity_id=entity_id, image_type="product", image_format="cover" ) result = fixture_client.get(request_url, headers=ALW_HEADERS) # checking assert result.status_code == 403 assert result.headers.get("Correlation-Id") def test_get_image_location_v1_permission_failure(fixture_client: FlaskClient) -> None: """Test permission failure of route for getting v1 image location.""" # mocking entity_id = 123456 flexmock(ownership).should_receive("check_ownership").and_return( response.create_error_response( code="not_owned", message="not_owned", status=403 ) ) flexmock(image_location_legacy).should_receive("get_image_location").with_args( entity_id, "product", "cover" ).and_return({1: "image_url"}) # test function call request_url = "/image/{image_type}/{image_format}/{entity_id}/location".format( entity_id=entity_id, image_type="product", image_format="cover" ) result = fixture_client.get(request_url, headers=ALW_HEADERS) # checking assert result.status_code == 403 assert result.headers.get("Correlation-Id") def test_get_image_locations_with_entity_ids(fixture_client: FlaskClient) -> None: """Test route for getting image locations in bulk.""" entities = [1001, 1002] entity_ids_query_params = "1001,1002" mocked_logic_response = { 1001: "https://qa-images.theorchard.io/product/cover/202cb962ac59075b964b07152d234b70.jpg", 1002: "https://qa-images.theorchard.io/product/cover/68053af2923e00204c3ca7c6a3150cf7.jpg", } flexmock(image_location).should_receive("get_image_locations").with_args( ids=entities, image_format="cover", fallback=True, omit_corrections=False ).and_return(mocked_logic_response) request_url = "/image/product/cover/location?ids={ids}".format( ids=entity_ids_query_params ) result = fixture_client.get(request_url) assert result.status_code == 200 assert result.headers.get("Correlation-Id") def test_get_image_locations_with_fallback_disabled( fixture_client: FlaskClient, ) -> None: """Test route for getting image locations in bulk with fallback disabled.""" entities = [1001, 1002] entity_ids_query_params = "1001,1002" mocked_logic_response = { 1001: "https://qa-images.theorchard.io/product/cover/202cb962ac59075b964b07152d234b70.jpg", 1002: "https://qa-images.theorchard.io/product/cover/68053af2923e00204c3ca7c6a3150cf7.jpg", } flexmock(image_location).should_receive("get_image_locations").with_args( ids=entities, image_format="cover", fallback=False, omit_corrections=False ).and_return(mocked_logic_response) request_url = "/image/product/cover/location?ids={ids}&fallback=0".format( ids=entity_ids_query_params ) result = fixture_client.get(request_url) assert result.status_code == 200 assert result.headers.get("Correlation-Id") def test_get_image_locations_with_post(fixture_client: FlaskClient) -> None: """Test route for getting image locations in bulk.""" entities = { "entities": [ {"product_id": 1001, "upc": "123"}, {"product_id": 1002, "upc": "456"}, {"product_id": 1003, "upc": "789"}, ] } mocked_logic_response = { 1001: "https://d14bv7mbq8je1y.cloudfront.net/123.jpg", 1002: "https://d14bv7mbq8je1y.cloudfront.net/456.jpg", 1003: "https://d14bv7mbq8je1y.cloudfront.net/789.jpg", } flexmock(image_location).should_receive("get_image_locations").with_args( entities["entities"], "xlarge_cover", fallback=True, omit_corrections=False ).and_return(mocked_logic_response) request_url = "/image/product/xlarge_cover/location" headers = {"Content-Type": "application/json"} result = fixture_client.post( request_url, data=json.dumps(entities), headers=headers ) assert result.status_code == 200 assert result.headers.get("Correlation-Id") def test_get_vendor_image(fixture_client: FlaskClient) -> None: """Test retrieving a vendor image.""" flexmock(image_location_legacy).should_receive("get_vendor_icon").and_return("url") request_url = "/image/vendor/{vendor_id}/asset/{asset_id}".format( vendor_id=123, asset_id=456 ) result = fixture_client.get(request_url) assert result.status_code == 200 assert result.data.decode("utf-8") == "url" @pytest.mark.parametrize("headers", [OA_HEADERS, ALW_HEADERS, {}]) def test_copy_product_artwork_success( monkeypatch: MonkeyPatch, fixture_client: FlaskClient, headers: dict[str, str] ) -> None: """Test copy product artwork assets.""" monkeypatch.setattr( asset_copy, "copy_artwork_assets", value=MagicMock(return_value=None), ) request_url = "/image/{0}/copy/{1}".format(10, 20) data = {} if not headers: data = {"Orchard-User-Id": "alw:321"} headers["Content-Type"] = "application/json" result = fixture_client.post(request_url, data=json.dumps(data), headers=headers) assert result.status_code == 200 assert result.headers.get("Correlation-Id") @pytest.mark.parametrize("headers", [OA_HEADERS, ALW_HEADERS]) def test_copy_product_artwork_failure_logic_layer( monkeypatch: MonkeyPatch, fixture_client: FlaskClient, headers: dict[str, str] ) -> None: """Test copy product artwork assets logic layer failure.""" monkeypatch.setattr( ownership, "check_ownership", value=MagicMock(return_value=response.Response()) ) monkeypatch.setattr( asset_copy, "copy_artwork_assets", value=MagicMock( side_effect=AssetUploadError("Failed to create asset_upload record") ), ) request_url_pattern = "/image/{0}/copy/{1}" request_url = request_url_pattern.format(10, 20) result = fixture_client.post(request_url, headers=headers) assert result.status_code == 500 assert result.headers.get("Correlation-Id")