From c872f7243434a39c40ba2c0e13e740ffbf0ad182 Mon Sep 17 00:00:00 2001 From: Albert Sola Date: Thu, 13 Nov 2025 12:36:02 +0000 Subject: [PATCH] MPT-14886 Add E2E tests for catalog product parameters --- e2e_config.test.json | 1 + seed/catalog/product.py | 7 ++- seed/catalog/product_parameters.py | 14 ++--- seed/context.py | 4 ++ seed/main.py | 2 +- setup.cfg | 1 + tests/e2e/catalog/product/conftest.py | 10 ++++ .../product/parameter_groups/conftest.py | 5 -- .../catalog/product/parameters/conftest.py | 21 +++++++ .../parameters/test_async_parameters.py | 53 ++++++++++++++++++ .../parameters/test_sync_parameters.py | 56 +++++++++++++++++++ tests/seed/catalog/test_product_parameters.py | 10 ++-- 12 files changed, 164 insertions(+), 20 deletions(-) create mode 100644 tests/e2e/catalog/product/parameters/conftest.py create mode 100644 tests/e2e/catalog/product/parameters/test_async_parameters.py create mode 100644 tests/e2e/catalog/product/parameters/test_sync_parameters.py diff --git a/e2e_config.test.json b/e2e_config.test.json index 6c11b041..31a819fd 100644 --- a/e2e_config.test.json +++ b/e2e_config.test.json @@ -2,5 +2,6 @@ "catalog.product.id": "PRD-7255-3950", "accounts.seller.id": "SEL-7310-3075", "catalog.product.parameter_group.id": "PGR-7255-3950-0001", + "catalog.product.parameter.id": "PAR-7255-3950-0016", "accounts.account.id": "ACC-9042-0088" } diff --git a/seed/catalog/product.py b/seed/catalog/product.py index 2f721845..01c73a98 100644 --- a/seed/catalog/product.py +++ b/seed/catalog/product.py @@ -22,6 +22,7 @@ async def get_product( ) -> Product | None: """Get product from context or fetch from API.""" product_id = context.get_string(f"{namespace}.id") + logger.debug("Getting product: %s", product_id) if not product_id: return None try: @@ -44,7 +45,7 @@ async def init_product( ) -> Product: """Get or create product.""" product = await get_product() - if not product: + if product is None: logger.debug("Creating product ...") with pathlib.Path.open(icon, "rb") as icon_file: product = await mpt_vendor.catalog.products.create( @@ -52,7 +53,9 @@ async def init_product( ) context.set_resource(namespace, product) context[f"{namespace}.id"] = product.id - logger.debug("Product created: %s", product.id) + logger.info("Product created: %s", product.id) + else: + logger.info("Product found: %s", product.id) return product diff --git a/seed/catalog/product_parameters.py b/seed/catalog/product_parameters.py index 98ba7ef4..e8a36a20 100644 --- a/seed/catalog/product_parameters.py +++ b/seed/catalog/product_parameters.py @@ -10,7 +10,7 @@ logger = logging.getLogger(__name__) -namespace = "catalog.parameter" +namespace = "catalog.product.parameter" @inject @@ -35,15 +35,15 @@ async def get_parameter( @inject def build_parameter(context: Context = DEFAULT_CONTEXT) -> dict[str, Any]: """Build parameter data dictionary.""" - parameter_group_id = context.get_string("catalog.parameter_group.id") + parameter_group_id = context.get_string("catalog.product.parameter_group.id") if not parameter_group_id: raise ValueError("Parameter group id is required.") return { - "name": "Parameter Name", + "name": "e2e - seed", "scope": "Order", "phase": "Order", - "description": "Agreement identifier of the reseller", - "externalId": "RES-233-33-xx3", + "description": "e2e - seeded parameter", + "externalId": "e2e-seed-parameter", "displayOrder": 100, "context": "Purchase", "constraints": {"hidden": True, "readonly": True, "required": False}, @@ -71,7 +71,7 @@ async def create_parameter( raise ValueError("Product id is required.") parameter_data = build_parameter(context=context) parameter = await mpt_vendor.catalog.products.parameters(product_id).create(parameter_data) - logger.debug("Parameter created: %s", parameter.id) + logger.info("Parameter created: %s", parameter.id) context[f"{namespace}.id"] = parameter.id context.set_resource(namespace, parameter) return parameter @@ -87,7 +87,7 @@ async def init_parameter( if not parameter: logger.debug("Creating parameter ...") - return await create_parameter(context, mpt_vendor) + return await create_parameter(context=context, mpt_vendor=mpt_vendor) logger.debug("Parameter found: %s", parameter.id) return parameter diff --git a/seed/context.py b/seed/context.py index e89b2eca..d086a2ef 100644 --- a/seed/context.py +++ b/seed/context.py @@ -1,10 +1,13 @@ import collections import json +import logging import pathlib from typing import Any from mpt_api_client.models import Model +logger = logging.getLogger(__name__) + class Context(collections.UserDict[str, Any]): """Application context.""" @@ -45,6 +48,7 @@ def load_context(json_file: pathlib.Path, context: Context | None = None) -> Con with json_file.open("r", encoding="utf-8") as fd: existing_data = json.load(fd) context.update(existing_data) + logger.info("Context loaded: %s", context.items()) return context diff --git a/seed/main.py b/seed/main.py index e346a948..de5c7a16 100644 --- a/seed/main.py +++ b/seed/main.py @@ -4,7 +4,7 @@ from seed.container import wire_container from seed.seed_api import seed_api -logging.basicConfig(level=logging.INFO) +logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger(__name__) diff --git a/setup.cfg b/setup.cfg index 4bbe6d39..8297cbe4 100644 --- a/setup.cfg +++ b/setup.cfg @@ -49,6 +49,7 @@ per-file-ignores = tests/unit/resources/accounts/test_users.py: WPS204 WPS202 WPS210 tests/unit/test_mpt_client.py: WPS235 tests/e2e/accounts/*.py: WPS430 WPS202 + tests/e2e/catalog/*.py: WPS421 tests/*: # Allow magic strings. diff --git a/tests/e2e/catalog/product/conftest.py b/tests/e2e/catalog/product/conftest.py index 9a09b76e..3350ada9 100644 --- a/tests/e2e/catalog/product/conftest.py +++ b/tests/e2e/catalog/product/conftest.py @@ -12,3 +12,13 @@ def product_icon(): @pytest.fixture def product_data(): return {"name": "Test Product", "website": "https://www.example.com"} + + +@pytest.fixture +def parameter_group_id(e2e_config): + return e2e_config["catalog.product.parameter_group.id"] + + +@pytest.fixture +def parameter_id(e2e_config): + return e2e_config["catalog.product.parameter.id"] diff --git a/tests/e2e/catalog/product/parameter_groups/conftest.py b/tests/e2e/catalog/product/parameter_groups/conftest.py index 138dee6c..9e24d798 100644 --- a/tests/e2e/catalog/product/parameter_groups/conftest.py +++ b/tests/e2e/catalog/product/parameter_groups/conftest.py @@ -1,11 +1,6 @@ import pytest -@pytest.fixture -def parameter_group_id(e2e_config): - return e2e_config["catalog.product.parameter_group.id"] - - @pytest.fixture def parameter_group_data(): return { diff --git a/tests/e2e/catalog/product/parameters/conftest.py b/tests/e2e/catalog/product/parameters/conftest.py new file mode 100644 index 00000000..a21e96f3 --- /dev/null +++ b/tests/e2e/catalog/product/parameters/conftest.py @@ -0,0 +1,21 @@ +import pytest + + +@pytest.fixture +def parameter_data(parameter_group_id): + return { + "constraints": {"hidden": False, "readonly": False, "required": False}, + "description": "e2e - please delete", + "displayOrder": 100, + "name": "e2e - please delete", + "phase": "Order", + "scope": "Order", + "type": "SingleLineText", + "context": "Purchase", + "options": { + "hintText": "delete", + "defaultValue": "Delete me", + "placeholderText": "Place holder text", + }, + "group": {"id": parameter_group_id}, + } diff --git a/tests/e2e/catalog/product/parameters/test_async_parameters.py b/tests/e2e/catalog/product/parameters/test_async_parameters.py new file mode 100644 index 00000000..edb427b1 --- /dev/null +++ b/tests/e2e/catalog/product/parameters/test_async_parameters.py @@ -0,0 +1,53 @@ +import pytest + +from mpt_api_client.exceptions import MPTAPIError + +pytestmark = [pytest.mark.flaky] + + +@pytest.fixture +async def async_created_parameter(async_mpt_vendor, product_id, parameter_data): + service = async_mpt_vendor.catalog.products.parameters(product_id) + parameter = await service.create(parameter_data) + yield parameter + try: + await service.delete(parameter.id) + except MPTAPIError as error: + print(f"TEARDOWN - Unable to delete parameter {parameter.id}: {error.title}") + + +def test_create_parameter(async_created_parameter): + assert async_created_parameter.name == "e2e - please delete" + + +async def test_create_parameter_wrong_data(async_mpt_vendor, product_id): + parameter_data = {"name": "e2e - please delete - wrong data test"} + service = async_mpt_vendor.catalog.products.parameters(product_id) + with pytest.raises(MPTAPIError): + await service.create(parameter_data) + + +async def test_update_parameter(async_mpt_vendor, product_id, async_created_parameter): + service = async_mpt_vendor.catalog.products.parameters(product_id) + update_data = {"name": "please delete me"} + parameter = await service.update(async_created_parameter.id, update_data) + assert parameter.name == "please delete me" + + +async def test_get_parameter(async_mpt_vendor, product_id, parameter_id): + service = async_mpt_vendor.catalog.products.parameters(product_id) + parameter = await service.get(parameter_id) + assert parameter.id == parameter_id + + +async def test_iterate_parameters(async_mpt_vendor, product_id, async_created_parameter): + service = async_mpt_vendor.catalog.products.parameters(product_id) + product_parameters = [product_param async for product_param in service.iterate()] + assert any(parameter.id == async_created_parameter.id for parameter in product_parameters) + + +async def test_delete_parameter(async_mpt_vendor, product_id, async_created_parameter): + service = async_mpt_vendor.catalog.products.parameters(product_id) + await service.delete(async_created_parameter.id) + parameter = await service.get(async_created_parameter.id) + assert parameter.status == "Deleted" diff --git a/tests/e2e/catalog/product/parameters/test_sync_parameters.py b/tests/e2e/catalog/product/parameters/test_sync_parameters.py new file mode 100644 index 00000000..30702a3e --- /dev/null +++ b/tests/e2e/catalog/product/parameters/test_sync_parameters.py @@ -0,0 +1,56 @@ +import pytest + +from mpt_api_client.exceptions import MPTAPIError + +pytestmark = [pytest.mark.flaky] + + +@pytest.fixture +def created_parameter(mpt_vendor, product_id, parameter_data): + service = mpt_vendor.catalog.products.parameters(product_id) + parameter = service.create(parameter_data) + yield parameter + try: + service.delete(parameter.id) + except MPTAPIError as error: + print(f"TEARDOWN - Unable to delete parameter {parameter.id}: {error.title}") + + +def test_create_parameter(created_parameter): + assert created_parameter.name == "e2e - please delete" + + +def test_create_parameter_wrong_data(mpt_vendor, product_id): + parameter_data = {"name": "e2e - please delete - wrong data test"} + service = mpt_vendor.catalog.products.parameters(product_id) + with pytest.raises(MPTAPIError): + service.create( + parameter_data, + ) + + +def test_update_parameter(mpt_vendor, product_id, created_parameter): + service = mpt_vendor.catalog.products.parameters(product_id) + update_data = {"name": "please delete me"} + parameter = service.update(created_parameter.id, update_data) + assert parameter.name == "please delete me" + + +def test_get_parameter(mpt_vendor, product_id, parameter_id): + service = mpt_vendor.catalog.products.parameters(product_id) + parameter = service.get(parameter_id) + assert parameter.id == parameter_id + + +def test_iterate_parameters(mpt_vendor, product_id, created_parameter): + service = mpt_vendor.catalog.products.parameters(product_id) + product_parameters = list(service.iterate()) + assert any(parameter.id == created_parameter.id for parameter in product_parameters) + + +def test_delete_parameter(mpt_vendor, product_id, created_parameter): + service = mpt_vendor.catalog.products.parameters(product_id) + service.delete(created_parameter.id) + + parameter = service.get(created_parameter.id) + assert parameter.status == "Deleted" diff --git a/tests/seed/catalog/test_product_parameters.py b/tests/seed/catalog/test_product_parameters.py index 2544b703..50737ded 100644 --- a/tests/seed/catalog/test_product_parameters.py +++ b/tests/seed/catalog/test_product_parameters.py @@ -14,7 +14,7 @@ ) from seed.context import Context -namespace = "catalog.parameter" +namespace = "catalog.product.parameter" @pytest.fixture @@ -55,7 +55,7 @@ async def test_get_parameter_without_id(context: Context) -> None: def test_build_parameter(context: Context) -> None: - context["catalog.parameter_group.id"] = "group-123" + context["catalog.product.parameter_group.id"] = "group-123" parameter_payload: dict[str, Any] = build_parameter(context=context) @@ -93,7 +93,7 @@ async def test_create_parameter_success( context: Context, vendor_client: AsyncMock, parameter: Parameter ) -> None: context["catalog.product.id"] = "product-123" - context["catalog.parameter_group.id"] = "group-123" + context["catalog.product.parameter_group.id"] = "group-123" service = AsyncMock(spec=AsyncParametersService) service.create.return_value = parameter vendor_client.catalog.products.parameters.return_value = service @@ -101,8 +101,8 @@ async def test_create_parameter_success( created = await create_parameter(context=context, mpt_vendor=vendor_client) assert created == parameter - assert context.get("catalog.parameter.id") == parameter.id - assert context.get(f"catalog.parameter[{parameter.id}]") == parameter + assert context.get("catalog.product.parameter.id") == parameter.id + assert context.get(f"catalog.product.parameter[{parameter.id}]") == parameter async def test_create_parameter_missing_product(context: Context, vendor_client: AsyncMock) -> None: