"""Functional tests for DELETE /product//spatial endpoint.""" from unittest.mock import MagicMock from flexmock import flexmock from owsrequest import request import pytest from product_digital.connectors import mysql from product_digital.constants import services from product_digital.models.product_additional_upc import ProductAdditionalUpc from product_digital.models.product_additional_upc import ProductAdditionalUpcType from tests.factories import release as release_factory from tests.factories import release_spatial as release_spatial_factory from tests.testutils import db PRODUCT_ID = 12345 SPATIAL_UPC = 9876543210123 @pytest.fixture def product_id(): """Return a fake product id for testing.""" return PRODUCT_ID @pytest.fixture def owner_ok_response(): """Return a mock 200 ownership response from ows-product.""" return MagicMock(status_code=200) @pytest.fixture def not_owner_response(): """Return a mock 403 ownership response from ows-product.""" return MagicMock(status_code=403) @db.test_schema def test_delete_product_spatial_success( client, product_id, valid_headers_for_vendor, owner_ok_response): """Test successful deletion of a spatial record.""" existing_release = release_factory.ReleaseFactory.build(release_id=product_id) existing_spatial = release_spatial_factory.ReleaseSpatialFactory.build( release_id=product_id, upc=SPATIAL_UPC) db.seed_models([existing_release, existing_spatial]) (flexmock(request) .should_receive('head') .and_return(owner_ok_response)) response = client.delete( '/products/{}/spatial'.format(product_id), headers=valid_headers_for_vendor) assert response.status_code == 200 @db.test_schema def test_delete_product_spatial_soft_deletes_mirror( client, product_id, valid_headers_for_vendor, owner_ok_response): """Deleting the release_spatial row soft-deletes the product_additional_upc mirror.""" existing_release = release_factory.ReleaseFactory.build(release_id=product_id) existing_spatial = release_spatial_factory.ReleaseSpatialFactory.build( release_id=product_id, upc=SPATIAL_UPC) db.seed_models([existing_release, existing_spatial]) with mysql.db_session() as session: session.add(ProductAdditionalUpc( product_id=product_id, type=ProductAdditionalUpcType.ATMOS, upc=SPATIAL_UPC)) session.commit() (flexmock(request) .should_receive('head') .and_return(owner_ok_response)) response = client.delete( '/products/{}/spatial'.format(product_id), headers=valid_headers_for_vendor) assert response.status_code == 200 with mysql.db_session() as session: mirror = session.query(ProductAdditionalUpc).filter( ProductAdditionalUpc.product_id == product_id).one() assert mirror.deleted_at is not None @db.test_schema def test_delete_product_spatial_not_found( client, product_id, valid_headers_for_vendor, owner_ok_response): """Test 404 when no spatial record exists for the product.""" existing_release = release_factory.ReleaseFactory.build(release_id=product_id) db.seed_models(existing_release) (flexmock(request) .should_receive('head') .and_return(owner_ok_response)) response = client.delete( '/products/{}/spatial'.format(product_id), headers=valid_headers_for_vendor) assert response.status_code == 404 def test_delete_product_spatial_not_owner( client, product_id, account_id, valid_headers_for_vendor, not_owner_response): """Test 403 when the requesting account does not own the product.""" (flexmock(request) .should_receive('head') .with_args(services.OWS_PRODUCT, '/vendor/{}/product/{}'.format( account_id, product_id)) .and_return(not_owner_response)) response = client.delete( '/products/{}/spatial'.format(product_id), headers=valid_headers_for_vendor) assert response.status_code == 403 def test_delete_product_spatial_incomplete_grass_headers( client, product_id, valid_headers, account_id): """Test 400 when only one Grass header is present (incomplete pair).""" valid_headers['Grass-Account-Id'] = account_id response = client.delete( '/products/{}/spatial'.format(product_id), headers=valid_headers) assert response.status_code == 400