"""Tests for the vendor-contract store-carveout dataloader endpoint. POST /vendor-contract-store-carveouts-dataloader is listed in carveouts/access_rules.yml as requiring an OrchAdminProfile, so a black-box caller must be authenticated as an admin to reach the handler's own schema validation. These tests therefore SKIP unless an admin auth header is supplied (TEST_ADMIN_AUTH_HEADER / TEST_ADMIN_AUTH_VALUE). The endpoint only reads carveout data for the supplied pairs (it does not mutate), so the happy-path test is safe to run against shared environments. """ import pytest import requests from tests.integration.consts import api from tests.integration.utils import assert_ok requires_admin = pytest.mark.skipif( not (api.ADMIN_AUTH_HEADER and api.ADMIN_AUTH_VALUE), reason="needs TEST_ADMIN_AUTH_HEADER and TEST_ADMIN_AUTH_VALUE", ) requires_dataloader_data = pytest.mark.skipif( not (api.DATALOADER_VENDOR_CONTRACT_ID and api.DATALOADER_DELIVERY_STORE_ID), reason="needs TEST_DATALOADER_VENDOR_CONTRACT_ID and " "TEST_DATALOADER_DELIVERY_STORE_ID", ) def _admin_headers() -> dict[str, str]: return {(api.ADMIN_AUTH_HEADER or ""): (api.ADMIN_AUTH_VALUE or "")} @pytest.mark.negative @requires_admin def test_dataloader_schema_invalid_body_rejected() -> None: """A body with an unknown field violates the schema and is rejected 400. Validation runs before any lookup, so nothing is read or written. """ body = [{"unknown_field": 1, "delivery_store_id": 2}] response = requests.post( api.DATALOADER, json=body, headers=_admin_headers(), timeout=api.REQUEST_TIMEOUT ) assert response.status_code == 400, f"\nURL: {response.url}\nBody: {response.text}" @pytest.mark.negative @requires_admin def test_dataloader_non_list_body_rejected() -> None: """The payload must be a list of pairs; an object is rejected with 400.""" response = requests.post( api.DATALOADER, json={}, headers=_admin_headers(), timeout=api.REQUEST_TIMEOUT ) assert response.status_code == 400, f"\nURL: {response.url}\nBody: {response.text}" @pytest.mark.read @requires_admin @requires_dataloader_data def test_dataloader_returns_result_per_pair() -> None: """A valid pair returns a 200 with one result entry containing `data`.""" body = [ { "vendor_contract_id": int(api.DATALOADER_VENDOR_CONTRACT_ID or 0), "delivery_store_id": int(api.DATALOADER_DELIVERY_STORE_ID or 0), } ] response = requests.post( api.DATALOADER, json=body, headers=_admin_headers(), timeout=api.REQUEST_TIMEOUT ) # flaskify serializes OwsResponse.message (a list) directly, so the body is # a bare JSON list mirroring the input order, one entry per requested pair, # each carrying a `data` key (null when the pair has no carveout). payload = assert_ok(response).json() assert isinstance(payload, list) assert len(payload) == len(body) assert "data" in payload[0]