diff --git a/seed/__init__.py b/seed/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/seed/accounts/__init__.py b/seed/accounts/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/seed/accounts/accounts.py b/seed/accounts/accounts.py deleted file mode 100644 index 858fba0..0000000 --- a/seed/accounts/accounts.py +++ /dev/null @@ -1,36 +0,0 @@ -import logging -import os - -from mpt_api_client.resources.accounts.account import Account -from seed.accounts.api_tokens import seed_api_token -from seed.accounts.buyer import seed_buyer -from seed.accounts.licensee import seed_licensee -from seed.accounts.module import seed_module -from seed.accounts.seller import seed_seller -from seed.accounts.user_group import seed_user_group -from seed.helper import init_resource - -logger = logging.getLogger(__name__) - - -async def get_account() -> Account: # noqa: RUF029 async for compatibility purposes with init_resource - """Get account ID from environment variable.""" - account_id = os.getenv("CLIENT_ACCOUNT_ID") - if not account_id: - raise ValueError("CLIENT_ACCOUNT_ID environment variable is required") - return Account({"id": account_id}) - - -async def seed_accounts() -> None: # noqa: WPS213 WPS217 - """Seed accounts data including account.""" - logger.debug("Seeding accounts ...") - await init_resource("accounts.account.id", get_account) - - await seed_seller() - await seed_buyer() - await seed_module() - await seed_api_token() - await seed_user_group() - await seed_licensee() - - logger.debug("Seeded accounts completed.") diff --git a/seed/accounts/api_tokens.py b/seed/accounts/api_tokens.py deleted file mode 100644 index 4673576..0000000 --- a/seed/accounts/api_tokens.py +++ /dev/null @@ -1,43 +0,0 @@ -import logging - -from dependency_injector.wiring import Provide, inject - -from mpt_api_client import AsyncMPTClient -from mpt_api_client.resources.accounts.api_tokens import ApiToken -from seed.container import Container -from seed.context import Context -from seed.helper import init_resource, require_context_id - -logger = logging.getLogger(__name__) - - -@inject -def build_api_token_data( - context: Context = Provide[Container.context], -) -> dict[str, object]: - """Get API token data dictionary for creation.""" - account_id = require_context_id(context, "accounts.account.id", "creating API token") - module_id = require_context_id(context, "accounts.module.id", "creating API token") - return { - "account": {"id": account_id}, - "name": "E2E Seeded API Token", - "description": "This is a seeded API token for end-to-end testing.", - "icon": "", - "modules": [{"id": module_id}], - } - - -@inject -async def create_api_token( - mpt_ops: AsyncMPTClient = Provide[Container.mpt_operations], -) -> ApiToken: - """Creates an API token.""" - api_token_data = build_api_token_data() - return await mpt_ops.accounts.api_tokens.create(api_token_data) - - -async def seed_api_token() -> None: - """Seed API token.""" - logger.debug("Seeding API token ...") - await init_resource("accounts.api_token.id", create_api_token) - logger.debug("Seeding API token completed.") diff --git a/seed/accounts/buyer.py b/seed/accounts/buyer.py deleted file mode 100644 index c8a6781..0000000 --- a/seed/accounts/buyer.py +++ /dev/null @@ -1,53 +0,0 @@ -import logging - -from dependency_injector.wiring import Provide, inject - -from mpt_api_client import AsyncMPTClient -from mpt_api_client.resources.accounts.buyers import Buyer -from seed.container import Container -from seed.context import Context -from seed.helper import init_resource, require_context_id -from seed.static.static import ICON - -logger = logging.getLogger(__name__) - - -def build_buyer_data(context: Context = Provide[Container.context]) -> dict[str, object]: - """Build buyer data dictionary for creation.""" - buyer_account_id = require_context_id(context, "accounts.account.id", "creating buyer") - seller_id = require_context_id(context, "accounts.seller.id", "creating buyer") - return { - "name": "E2E Seeded Buyer", - "account": {"id": buyer_account_id}, - "sellers": [{"id": seller_id}], - "contact": { - "firstName": "first", - "lastName": "last", - "email": "created.buyer@example.com", - }, - "address": { - "addressLine1": "123 Main St", - "city": "Los Angeles", - "state": "CA", - "postCode": "12345", - "country": "US", - }, - } - - -@inject -async def create_buyer( - context: Context = Provide[Container.context], - mpt_operations: AsyncMPTClient = Provide[Container.mpt_operations], -) -> Buyer: - """Creates a buyer.""" - buyer_data = build_buyer_data(context=context) - with ICON.open("rb") as icon_fd: - return await mpt_operations.accounts.buyers.create(buyer_data, file=icon_fd) - - -async def seed_buyer() -> None: - """Seed buyer.""" - logger.debug("Seeding buyer ...") - await init_resource("accounts.buyer.id", create_buyer) - logger.debug("Seeding buyer completed.") diff --git a/seed/accounts/licensee.py b/seed/accounts/licensee.py deleted file mode 100644 index c418fdd..0000000 --- a/seed/accounts/licensee.py +++ /dev/null @@ -1,59 +0,0 @@ -import logging - -from dependency_injector.wiring import Provide, inject - -from mpt_api_client import AsyncMPTClient -from mpt_api_client.resources.accounts.licensees import Licensee -from seed.container import Container -from seed.context import Context -from seed.helper import init_resource, require_context_id -from seed.static.static import ICON - -logger = logging.getLogger(__name__) - - -@inject -def build_licensee_data( # noqa: WPS238 - context: Context = Provide[Container.context], -) -> dict[str, object]: - """Get licensee data dictionary for creation.""" - account_id = require_context_id(context, "accounts.account.id", "creating licensee") - seller_id = require_context_id(context, "accounts.seller.id", "create licensee") - buyer_id = require_context_id(context, "accounts.buyer.id", "create licensee") - user_group_id = require_context_id(context, "accounts.user_group.id", "create licensee") - - licensee_type = "Client" - return { - "name": "E2E Seeded Licensee", - "address": { - "addressLine1": "123 Main St", - "city": "Los Angeles", - "state": "CA", - "postCode": "67890", - "country": "US", - }, - "useBuyerAddress": False, - "seller": {"id": seller_id}, - "buyer": {"id": buyer_id}, - "account": {"id": account_id}, - "eligibility": {"client": True, "partner": False}, - "groups": [{"id": user_group_id}], - "type": licensee_type, - "status": "Enabled", - "defaultLanguage": "en-US", - } - - -@inject -async def create_licensee(mpt_client: AsyncMPTClient = Provide[Container.mpt_client]) -> Licensee: - """Create licensee.""" - licensee_data = build_licensee_data() - with ICON.open("rb") as icon_fd: - return await mpt_client.accounts.licensees.create(licensee_data, file=icon_fd) - - -async def seed_licensee() -> None: - """Seed licensee.""" - logger.debug("Seeding licensee ...") - await init_resource("accounts.licensee.id", create_licensee) - logger.info("Seeding licensee completed.") diff --git a/seed/accounts/module.py b/seed/accounts/module.py deleted file mode 100644 index 03735e3..0000000 --- a/seed/accounts/module.py +++ /dev/null @@ -1,34 +0,0 @@ -import logging - -from dependency_injector.wiring import Provide, inject - -from mpt_api_client import AsyncMPTClient -from mpt_api_client.resources.accounts.modules import Module -from mpt_api_client.rql.query_builder import RQLQuery -from seed.container import Container -from seed.helper import init_resource - -logger = logging.getLogger(__name__) - - -@inject -async def find_module( - mpt_operations: AsyncMPTClient = Provide[Container.mpt_operations], -) -> Module: - """Selects an existing module to use for seeding purposes. - - Currently selects the "Access Management" module from the marketplace. - """ - filtered = mpt_operations.accounts.modules.filter(RQLQuery(name="Access Management")) - modules = [module async for module in filtered.iterate()] - - if not modules: - raise ValueError("Module 'Access Management' not found.") - return modules[0] - - -async def seed_module() -> None: - """Seed module.""" - logger.debug("Seeding module ...") - await init_resource("accounts.module.id", find_module) - logger.debug("Seeding module completed.") diff --git a/seed/accounts/seller.py b/seed/accounts/seller.py deleted file mode 100644 index 610de87..0000000 --- a/seed/accounts/seller.py +++ /dev/null @@ -1,45 +0,0 @@ -import logging -import uuid - -from dependency_injector.wiring import Provide, inject - -from mpt_api_client import AsyncMPTClient -from mpt_api_client.resources.accounts.sellers import Seller -from seed.container import Container -from seed.helper import init_resource - -logger = logging.getLogger(__name__) - - -def build_seller_data(external_id: str | None = None) -> dict[str, object]: - """Get seller data dictionary for creation.""" - if external_id is None: - external_id = f"ext-{uuid.uuid4()}" - return { - "name": "E2E Seeded Seller", - "address": { - "addressLine1": "123 Main St", - "city": "Los Angeles", - "state": "CA", - "postCode": "12345", - "country": "US", - }, - "currencies": ["USD", "EUR"], - "externalId": external_id, # Must be unique in Marketplace - } - - -@inject -async def create_seller( - mpt_operations: AsyncMPTClient = Provide[Container.mpt_operations], -) -> Seller: - """Creates a seller.""" - seller_data = build_seller_data() - return await mpt_operations.accounts.sellers.create(seller_data) - - -async def seed_seller() -> None: - """Seed seller.""" - logger.debug("Seeding seller ...") - await init_resource("accounts.seller.id", create_seller) - logger.debug("Seeding seller completed.") diff --git a/seed/accounts/user_group.py b/seed/accounts/user_group.py deleted file mode 100644 index ccb8e9d..0000000 --- a/seed/accounts/user_group.py +++ /dev/null @@ -1,45 +0,0 @@ -# mypy: disable-error-code=unreachable -import logging - -from dependency_injector.wiring import Provide, inject - -from mpt_api_client import AsyncMPTClient -from mpt_api_client.resources.accounts.user_groups import UserGroup -from seed.container import Container -from seed.context import Context -from seed.helper import init_resource, require_context_id - -logger = logging.getLogger(__name__) - - -@inject -def build_user_group_data( - context: Context = Provide[Container.context], -) -> dict[str, object]: - """Get user group data dictionary for creation.""" - account_id = require_context_id(context, "accounts.account.id", "create user group") - module_id = require_context_id(context, "accounts.module.id", "create user group") - return { - "name": "E2E Seeded User Group", - "account": {"id": account_id}, - "buyers": None, - "logo": "", - "description": "User group for E2E tests", - "modules": [{"id": module_id}], - } - - -@inject -async def create_user_group( - mpt_operations: AsyncMPTClient = Provide[Container.mpt_operations], -) -> UserGroup: - """Creates a user group.""" - user_group_data = build_user_group_data() - return await mpt_operations.accounts.user_groups.create(user_group_data) - - -async def seed_user_group() -> None: - """Seed user group.""" - logger.debug("Seeding user group ...") - await init_resource("accounts.user_group.id", create_user_group) - logger.debug("Seeding user group completed.") diff --git a/seed/catalog/__init__.py b/seed/catalog/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/seed/catalog/authorization.py b/seed/catalog/authorization.py deleted file mode 100644 index c462e54..0000000 --- a/seed/catalog/authorization.py +++ /dev/null @@ -1,39 +0,0 @@ -import uuid - -from dependency_injector.wiring import Provide, inject - -from mpt_api_client import AsyncMPTClient -from mpt_api_client.resources.catalog.authorizations import Authorization -from seed.container import Container -from seed.context import Context -from seed.helper import init_resource, require_context_id - - -async def seed_authorization() -> None: - """Seed authorization.""" - await init_resource("catalog.authorization.id", create_authorization) - - -@inject -async def create_authorization( - operations: AsyncMPTClient = Provide[Container.mpt_operations], - context: Context = Provide[Container.context], -) -> Authorization: - """Creates an authorization.""" - product_id = require_context_id(context, "catalog.product.id", "Create authorization") - seller_id = require_context_id(context, "accounts.seller.id", "Create authorization") - account_id = require_context_id(context, "accounts.account.id", "Create authorization") - short_uuid = uuid.uuid4().hex[:8] - - authorization_data = { - "externalIds": {"operations": f"e2e-seeded-{short_uuid}"}, - "product": {"id": product_id}, - "owner": {"id": seller_id}, - "journal": {"firstInvoiceDate": "2025-12-01", "frequency": "1m"}, - "eligibility": {"client": True, "partner": True}, - "currency": "USD", - "notes": "E2E Seeded", - "name": "E2E Seeded", - "vendor": {"id": account_id}, - } - return await operations.catalog.authorizations.create(authorization_data) diff --git a/seed/catalog/catalog.py b/seed/catalog/catalog.py deleted file mode 100644 index 9117b2d..0000000 --- a/seed/catalog/catalog.py +++ /dev/null @@ -1,19 +0,0 @@ -import logging - -from seed.catalog.authorization import seed_authorization -from seed.catalog.listing import seed_listing -from seed.catalog.price_list import seed_price_list -from seed.catalog.product import seed_product - -logger = logging.getLogger(__name__) - - -async def seed_catalog() -> None: - """Seed catalog data including products, item groups, and parameters.""" - logger.debug("Seeding catalog ...") - await seed_product() - await seed_authorization() - await seed_price_list() - await seed_listing() - - logger.debug("Seeded catalog completed.") diff --git a/seed/catalog/listing.py b/seed/catalog/listing.py deleted file mode 100644 index d800499..0000000 --- a/seed/catalog/listing.py +++ /dev/null @@ -1,46 +0,0 @@ -from dependency_injector.wiring import Provide, inject - -from mpt_api_client import AsyncMPTClient -from mpt_api_client.resources.catalog.listings import Listing -from seed.container import Container -from seed.context import Context -from seed.helper import init_resource, require_context_id - - -async def seed_listing() -> None: - """Seed listing.""" - await init_resource("catalog.listing.id", create_listing) - - -@inject -async def create_listing( # noqa: WPS210 - operations: AsyncMPTClient = Provide[Container.mpt_operations], - context: Context = Provide[Container.context], -) -> Listing: - """Creates a listing.""" - product_id = require_context_id(context, "catalog.product.id", "Create listing") - seller_id = require_context_id(context, "accounts.seller.id", "Create listing") - authorization_id = require_context_id(context, "catalog.authorization.id", "Create listing") - account_id = require_context_id(context, "accounts.account.id", "Create listing") - price_list_id = require_context_id(context, "catalog.price_list.id", "Create listing") - - listing_data = { - "name": "e2e - please delete", - "authorization": { - "id": authorization_id, - }, - "product": { - "id": product_id, - }, - "vendor": { - "id": account_id, - }, - "seller": { - "id": seller_id, - }, - "priceList": {"id": price_list_id}, - "primary": False, - "notes": "", - "eligibility": {"client": True, "partner": False}, - } - return await operations.catalog.listings.create(listing_data) diff --git a/seed/catalog/price_list.py b/seed/catalog/price_list.py deleted file mode 100644 index 6f85a4c..0000000 --- a/seed/catalog/price_list.py +++ /dev/null @@ -1,30 +0,0 @@ -from dependency_injector.wiring import Provide, inject - -from mpt_api_client import AsyncMPTClient -from mpt_api_client.resources.catalog.price_lists import PriceList -from seed.container import Container -from seed.context import Context -from seed.helper import init_resource, require_context_id - - -async def seed_price_list() -> None: - """Seed price list.""" - await init_resource("catalog.price_list.id", create_price_list) - - -@inject -async def create_price_list( - operations: AsyncMPTClient = Provide[Container.mpt_operations], - context: Context = Provide[Container.context], -) -> PriceList: - """Creates a price list.""" - product_id = require_context_id(context, "catalog.product.id", "Create price list") - - price_list_data = { - "notes": "E2E Seeded", - "defaultMarkup": "20.0", - "product": {"id": product_id}, - "currency": "USD", - "default": False, - } - return await operations.catalog.price_lists.create(price_list_data) diff --git a/seed/catalog/product.py b/seed/catalog/product.py deleted file mode 100644 index 904ec16..0000000 --- a/seed/catalog/product.py +++ /dev/null @@ -1,252 +0,0 @@ -import logging -import uuid - -from dependency_injector.wiring import Provide, inject - -from mpt_api_client import AsyncMPTClient -from mpt_api_client.resources.catalog.items import Item -from mpt_api_client.resources.catalog.product_term_variants import TermVariant -from mpt_api_client.resources.catalog.product_terms import Term -from mpt_api_client.resources.catalog.products import Product -from mpt_api_client.resources.catalog.products_documents import Document -from mpt_api_client.resources.catalog.products_item_groups import ItemGroup -from mpt_api_client.resources.catalog.products_parameter_groups import ParameterGroup -from mpt_api_client.resources.catalog.products_parameters import Parameter -from mpt_api_client.resources.catalog.products_templates import Template -from mpt_api_client.resources.catalog.units_of_measure import UnitOfMeasure -from seed.container import Container -from seed.context import Context -from seed.helper import init_resource, require_context_id -from seed.static.static import ICON, PDF - -logger = logging.getLogger(__name__) - - -@inject -async def create_product( - mpt_vendor: AsyncMPTClient = Provide[Container.mpt_vendor], -) -> Product: - """Creates a product.""" - logger.debug("Creating product ...") - with ICON.open("rb") as icon_fd: - return await mpt_vendor.catalog.products.create( - {"name": "E2E Seeded", "website": "https://www.example.com"}, file=icon_fd - ) - - -async def seed_product() -> None: - """Seed product data.""" - logger.debug("Seeding catalog.product ...") - await init_resource("catalog.product.id", create_product) - await publish_product() - await init_resource("catalog.unit.id", create_unit_of_measure) - await init_resource("catalog.product.item_group.id", create_item_group) - await init_resource("catalog.product.item.id", create_product_item) - await init_resource("catalog.product.document.id", create_document) - await init_resource("catalog.product.parameter_group.id", create_parameter_group) - await init_resource("catalog.product.parameter.id", create_parameter) - await init_resource("catalog.product.template.id", create_template) - await init_resource("catalog.product.terms.id", create_terms) - await init_resource("catalog.product.terms.variant.id", create_terms_variant) - logger.debug("Seeded catalog.product completed.") - - -@inject -async def publish_product( - context: Context = Provide[Container.context], - mpt_vendor: AsyncMPTClient = Provide[Container.mpt_vendor], - mpt_operations: AsyncMPTClient = Provide[Container.mpt_operations], -) -> None: - """Publish product.""" - product_id = require_context_id(context, "catalog.product.id", "publish product") - product = await mpt_vendor.catalog.products.get(product_id) - if product.status == "Draft": - product = await mpt_vendor.catalog.products.review(product_id) - if product.status in {"Pending", "Unpublished"}: - product = await mpt_operations.catalog.products.publish(product_id) - if product.status != "Published": - raise RuntimeError(f"Product {product_id} is not published") - - -@inject -async def create_terms_variant( - context: Context = Provide[Container.context], - mpt_vendor: AsyncMPTClient = Provide[Container.mpt_vendor], -) -> TermVariant: - """Creates a product terms variant.""" - term_variant_data = { - "name": "E2E seeding", - "description": "Test variant description", - "languageCode": "en-gb", - "type": "File", - "assetUrl": "", - } - product_id = require_context_id(context, "catalog.product.id", "creating product terms variant") - terms_id = require_context_id( - context, "catalog.product.terms.id", "creating product terms variant" - ) - with PDF.open("rb") as pdf_fd: - return ( - await mpt_vendor.catalog.products.terms(product_id) - .variants(terms_id) - .create(term_variant_data, file=pdf_fd) - ) - - -@inject -async def create_template( - context: Context = Provide[Container.context], - mpt_vendor: AsyncMPTClient = Provide[Container.mpt_vendor], -) -> Template: - """Creates a product template.""" - template_data = { - "name": "E2E Seeding", - "description": "A template for testing", - "content": "template content", - "type": "OrderProcessing", - } - product_id = require_context_id(context, "catalog.product.id", "creating product template") - return await mpt_vendor.catalog.products.templates(product_id).create(template_data) - - -@inject -async def create_terms( - context: Context = Provide[Container.context], - mpt_vendor: AsyncMPTClient = Provide[Container.mpt_vendor], -) -> Term: - """Creates a product terms.""" - product_id = require_context_id(context, "catalog.product.id", "creating product terms") - return await mpt_vendor.catalog.products.terms(product_id).create({ - "name": "E2E seeded", - "description": "E2E seeded", - }) - - -@inject -async def create_parameter_group( - context: Context = Provide[Container.context], - mpt_vendor: AsyncMPTClient = Provide[Container.mpt_vendor], -) -> ParameterGroup: - """Creates a product parameter group.""" - product_id = require_context_id( - context, "catalog.product.id", "creating product parameter group" - ) - return await mpt_vendor.catalog.products.parameter_groups(product_id).create({ - "name": "E2E Seeded", - "label": "E2E Seeded", - "displayOrder": 100, - }) - - -@inject -async def create_parameter( - context: Context = Provide[Container.context], - mpt_vendor: AsyncMPTClient = Provide[Container.mpt_vendor], -) -> Parameter: - """Creates a product parameter.""" - parameter_group_id = require_context_id( - context, "catalog.product.parameter_group.id", "creating product parameter" - ) - parameter_data = { - "constraints": {"hidden": False, "readonly": False, "required": False}, - "description": "E2E seeded", - "displayOrder": 100, - "name": "E2E seeded", - "phase": "Order", - "scope": "Order", - "type": "SingleLineText", - "context": "Purchase", - "options": { - "hintText": "e2e seeded", - "defaultValue": "default value", - "placeholderText": "Place holder text", - }, - "group": {"id": parameter_group_id}, - } - product_id = require_context_id(context, "catalog.product.id", "creating product parameter") - return await mpt_vendor.catalog.products.parameters(product_id).create(parameter_data) - - -@inject -async def create_document( - context: Context = Provide[Container.context], - mpt_vendor: AsyncMPTClient = Provide[Container.mpt_vendor], -) -> Document: - """Creates a product document.""" - product_id = require_context_id(context, "catalog.product.id", "creating product document") - document_data = { - "name": "E2E Seeded", - "description": "E2E Seeded", - "language": "en-gb", - "url": "", - "documenttype": "File", - } - with PDF.open("rb") as pdf_fd: - return await mpt_vendor.catalog.products.documents(product_id).create( - document_data, file=pdf_fd - ) - - -@inject -async def create_item_group( - context: Context = Provide[Container.context], - mpt_vendor: AsyncMPTClient = Provide[Container.mpt_vendor], -) -> ItemGroup: - """Creates a product item group.""" - product_id = require_context_id(context, "catalog.product.id", "creating product item group") - item_group_data = { - "product": {"id": product_id}, - "name": "E2E Seeded", - "label": "E2E Seeded", - "description": "E2E Seeded", - "displayOrder": 100, - "default": False, - "multiple": True, - "required": True, - } - - return await mpt_vendor.catalog.products.item_groups(product_id).create(item_group_data) - - -@inject -async def create_unit_of_measure( - operations: AsyncMPTClient = Provide[Container.mpt_operations], -) -> UnitOfMeasure: - """Creates a new unit of measure in the vendor's catalog.""" - short_uuid = uuid.uuid4().hex[:8] - return await operations.catalog.units_of_measure.create({ - "name": f"e2e seeded {short_uuid}", - "description": "e2e seeded", - }) - - -@inject -async def create_product_item( - context: Context = Provide[Container.context], - mpt_vendor: AsyncMPTClient = Provide[Container.mpt_vendor], -) -> Item: - """Creates a product item.""" - short_uuid = uuid.uuid4().hex[:8] - - unit_id = require_context_id(context, "catalog.unit.id", "creating product item") - item_group_id = require_context_id( - context, "catalog.product.item_group.id", "creating product item" - ) - product_id = require_context_id(context, "catalog.product.id", "creating product item") - - product_item_data = { - "name": "e2e - please delete", - "description": "e2e - please delete", - "unit": { - "id": unit_id, - }, - "group": { - "id": item_group_id, - }, - "product": { - "id": product_id, - }, - "terms": {"model": "quantity", "period": "1m", "commitment": "1m"}, - "externalIds": {"vendor": f"e2e-delete-{short_uuid}"}, - } - return await mpt_vendor.catalog.items.create(product_item_data) diff --git a/seed/container.py b/seed/container.py deleted file mode 100644 index ede91a6..0000000 --- a/seed/container.py +++ /dev/null @@ -1,43 +0,0 @@ -from dependency_injector import containers, providers - -from mpt_api_client import AsyncMPTClient -from seed.context import Context - - -class Container(containers.DeclarativeContainer): - """Dependency injection container for MPT clients.""" - - config = providers.Configuration() - - mpt_client = providers.Factory( - AsyncMPTClient.from_config, - api_token=config.mpt_api_token_client, - base_url=config.mpt_api_base_url, - ) - - mpt_vendor = providers.Factory( - AsyncMPTClient.from_config, - api_token=config.mpt_api_token_vendor, - base_url=config.mpt_api_base_url, - ) - - mpt_operations = providers.Factory( - AsyncMPTClient.from_config, - api_token=config.mpt_api_token_operations, - base_url=config.mpt_api_base_url, - ) - - context: providers.Singleton[Context] = providers.Singleton(Context) - - -container = Container() - -container.config.mpt_api_base_url.from_env("MPT_API_BASE_URL") -container.config.mpt_api_token_client.from_env("MPT_API_TOKEN_CLIENT") -container.config.mpt_api_token_vendor.from_env("MPT_API_TOKEN_VENDOR") -container.config.mpt_api_token_operations.from_env("MPT_API_TOKEN_OPERATIONS") - - -def wire_container() -> None: - """Wire the dependency injection container.""" - container.wire(packages=["seed"]) diff --git a/seed/context.py b/seed/context.py deleted file mode 100644 index 6c98e47..0000000 --- a/seed/context.py +++ /dev/null @@ -1,61 +0,0 @@ -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.""" - - def get_string(self, key: str, default: str = "") -> str: - """Get string value from context.""" - return str(self.get(key, default)) - - def get_resource(self, namespace: str, resource_id: str | None = None) -> Model: # noqa: WPS615 - """Get resource from context. - - Raises: - ValueError: if resource not found or wrong type. - """ - resource_id = resource_id or self.get_string(f"{namespace}.id") - resource = self.get(f"{namespace}[{resource_id}]") - if not isinstance(resource, Model): - raise ValueError(f"Resource {resource_id} not found.") # noqa: TRY004 - return resource - - def set_resource(self, namespace: str, resource: Model) -> None: # noqa: WPS615 - """Save resource to context.""" - self[f"{namespace}[{resource.id}]"] = resource - - -def load_context(json_file: pathlib.Path, context: Context) -> None: - """Load context from JSON file. - - Args: - json_file: JSON file path. - context: Context instance. - - Returns: - Context instance. - - """ - 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()) - - -def save_context(context: Context, json_file: pathlib.Path) -> None: - """Save context to JSON file. - - Args: - json_file: JSON file path. - context: Context instance. - """ - with json_file.open("w", encoding="utf-8") as fd: - json.dump(context.data, fd, indent=4, default=str) diff --git a/seed/helper.py b/seed/helper.py deleted file mode 100644 index 6cc4ae3..0000000 --- a/seed/helper.py +++ /dev/null @@ -1,84 +0,0 @@ -import logging -from collections.abc import Awaitable, Callable -from typing import Any - -from dependency_injector.wiring import Provide, inject - -from seed.container import Container -from seed.context import Context - -logger = logging.getLogger(__name__) - - -class ResourceRequiredError(Exception): - """Raised when a resource is required but not found.""" - - def __init__(self, context: Context, key: str, action: str): - super().__init__(f"Missing required resource '{key}' before {action}.") - self.context = context - self.key = key - self.action = action - - -def require_context_id(context: Context, key: str, action: str) -> str: - """Fetch an ID from context, ensuring it exists and is non-empty. - - Args: - context: The seeding context. - key: The expected context key where the id is stored. - action: A short description of what we are creating (for error message). - - Returns: - The id string stored in the context under the provided key. - - Raises: - ResourceRequiredError: If the id is missing or empty in context. - """ - resource_id = context.get_string(key) - if not resource_id: - raise ResourceRequiredError(context, key, action) - return resource_id - - -@inject -async def init_resource( - namespace: str, - resource_factory: Callable[[], Awaitable[Any]], - context: Context = Provide[Container.context], -) -> str: - """Initialize a resource on demand and cache its id in the Context. - - This helper reads an id from the provided Context at the given namespace. If the id - is missing or empty, it will call the provided async ``resource_factory`` to create - the resource, extract the ``id`` from the returned object, store it back into the - Context under ``namespace``, and return it. If the id already exists in the Context, - the factory is not called and the existing id is returned. - - Args: - namespace: The Context key where the resource id is stored (e.g., - "catalog.product.id"). - resource_factory: A zero-argument async callable that creates the resource when - needed. It must return an object with an ``id`` attribute (string-like). - context: The seeding Context used to read and persist the id. Defaults to - ``DEFAULT_CONTEXT``. - - Returns: - The resource id string, either retrieved from the Context or obtained from the - newly created resource. - - Notes: - - The factory is invoked only if the id is not already present in the Context. - - Any exceptions thrown by ``resource_factory`` will propagate to the caller. - - No additional validation of the returned id is performed beyond attribute access. - - Example: - In an async function/context you can do: - id_value = await init_resource("catalog.product.id", create_product, context) - """ - logger.debug("Initializing resource: %s", namespace) - id_value = context.get_string(namespace) - if not id_value: - resource = await resource_factory() - id_value = resource.id - context[namespace] = id_value - return id_value diff --git a/seed/main.py b/seed/main.py deleted file mode 100644 index de5c7a1..0000000 --- a/seed/main.py +++ /dev/null @@ -1,18 +0,0 @@ -import asyncio -import logging - -from seed.container import wire_container -from seed.seed_api import seed_api - -logging.basicConfig(level=logging.DEBUG) -logger = logging.getLogger(__name__) - - -async def main() -> None: - """Main entry point for seeding.""" - wire_container() - await seed_api() - - -if __name__ == "__main__": - asyncio.run(main()) diff --git a/seed/seed_api.py b/seed/seed_api.py deleted file mode 100644 index e9eed8a..0000000 --- a/seed/seed_api.py +++ /dev/null @@ -1,27 +0,0 @@ -import logging -import pathlib - -from dependency_injector.wiring import Provide, inject - -from seed.accounts.accounts import seed_accounts -from seed.catalog.catalog import seed_catalog -from seed.container import Container -from seed.context import Context, load_context, save_context - -logger = logging.getLogger(__name__) - -context_file: pathlib.Path = pathlib.Path(__file__).parent / "context.json" - - -@inject -async def seed_api(context: Context = Provide[Container.context]) -> None: - """Seed API.""" - load_context(context_file, context) - try: # noqa: WPS229 - await seed_accounts() - await seed_catalog() - logger.info("Seeding completed successfully.") - except Exception: - logger.exception("Exception occurred during seeding.") - finally: - save_context(context, context_file) diff --git a/seed/static/FIL-9920-4780-9379.png b/seed/static/FIL-9920-4780-9379.png deleted file mode 100644 index ab0c15a..0000000 Binary files a/seed/static/FIL-9920-4780-9379.png and /dev/null differ diff --git a/seed/static/__init__.py b/seed/static/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/seed/static/empty.pdf b/seed/static/empty.pdf deleted file mode 100644 index 5abbd77..0000000 Binary files a/seed/static/empty.pdf and /dev/null differ diff --git a/seed/static/logo.png b/seed/static/logo.png deleted file mode 100644 index ab9b8cf..0000000 Binary files a/seed/static/logo.png and /dev/null differ diff --git a/seed/static/static.py b/seed/static/static.py deleted file mode 100644 index 0ff8164..0000000 --- a/seed/static/static.py +++ /dev/null @@ -1,7 +0,0 @@ -import pathlib - -ICON = pathlib.Path(__file__).parent / "FIL-9920-4780-9379.png" - -LOGO = pathlib.Path(__file__).parent / "logo.png" - -PDF = pathlib.Path(__file__).parent / "empty.pdf" diff --git a/tests/seed/__init__.py b/tests/seed/__init__.py deleted file mode 100644 index 246a27c..0000000 --- a/tests/seed/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Tests for seed package.""" diff --git a/tests/seed/accounts/test_accounts.py b/tests/seed/accounts/test_accounts.py deleted file mode 100644 index 60fa9cf..0000000 --- a/tests/seed/accounts/test_accounts.py +++ /dev/null @@ -1,42 +0,0 @@ -import pytest - -from mpt_api_client.resources.accounts.account import Account -from seed.accounts.accounts import get_account, seed_accounts - - -async def test_get_account_fails(monkeypatch): - # when env var is missing -> raises - monkeypatch.delenv("CLIENT_ACCOUNT_ID", raising=False) - with pytest.raises(ValueError): - await get_account() - - -async def test_get_account_success(monkeypatch): - # when env var is present -> returns Account with same id - monkeypatch.setenv("CLIENT_ACCOUNT_ID", "ACC-123") - account = await get_account() - assert isinstance(account, Account) - assert account.id == "ACC-123" - - -async def test_seed_accounts(mocker): # noqa: WPS210 - mock_init_resource = mocker.patch("seed.accounts.accounts.init_resource", autospec=True) - - mock_seed_seller = mocker.patch("seed.accounts.accounts.seed_seller", autospec=True) - mock_seed_buyer = mocker.patch("seed.accounts.accounts.seed_buyer", autospec=True) - mock_seed_module = mocker.patch("seed.accounts.accounts.seed_module", autospec=True) - mock_seed_api_token = mocker.patch("seed.accounts.accounts.seed_api_token", autospec=True) - mock_seed_user_group = mocker.patch("seed.accounts.accounts.seed_user_group", autospec=True) - mock_seed_licensee = mocker.patch("seed.accounts.accounts.seed_licensee", autospec=True) - await seed_accounts() # act - mocks = [ - mock_seed_seller, - mock_seed_buyer, - mock_seed_module, - mock_seed_api_token, - mock_seed_user_group, - mock_seed_licensee, - mock_init_resource, - ] - for mock in mocks: - mock.assert_awaited_once() diff --git a/tests/seed/accounts/test_api_tokens.py b/tests/seed/accounts/test_api_tokens.py deleted file mode 100644 index 7fbf95e..0000000 --- a/tests/seed/accounts/test_api_tokens.py +++ /dev/null @@ -1,50 +0,0 @@ -import pytest - -from mpt_api_client.resources.accounts.api_tokens import ApiToken -from seed.accounts.api_tokens import ( - build_api_token_data, - create_api_token, - seed_api_token, -) - - -@pytest.fixture -def api_token(): - return ApiToken({"id": "TOK-123", "name": "Test Token"}) - - -def test_build_api_token_data(context, monkeypatch): - monkeypatch.setenv("CLIENT_ACCOUNT_ID", "ACC-1086-6867") - context["accounts.module.id"] = "MOD-456" - context["accounts.account.id"] = "ACC-1086-6867" - expected_data = { - "account": {"id": "ACC-1086-6867"}, - "name": "E2E Seeded API Token", - "description": "This is a seeded API token for end-to-end testing.", - "icon": "", - "modules": [{"id": "MOD-456"}], - } - - result = build_api_token_data(context=context) - - assert result == expected_data - - -async def test_create_api_token(mocker, api_token, operations_client): - create = mocker.AsyncMock(return_value=api_token) - operations_client.accounts.api_tokens.create = create - build_api_token_data = mocker.patch( - "seed.accounts.api_tokens.build_api_token_data", autospec=True - ) - - result = await create_api_token(operations_client) - - assert result == api_token - build_api_token_data.assert_called_once() - create.assert_awaited_once() - - -async def test_seed_api_token(mocker): - init_resource = mocker.patch("seed.accounts.api_tokens.init_resource", autospec=True) - await seed_api_token() # act - init_resource.assert_awaited_once() diff --git a/tests/seed/accounts/test_buyer.py b/tests/seed/accounts/test_buyer.py deleted file mode 100644 index 55e2679..0000000 --- a/tests/seed/accounts/test_buyer.py +++ /dev/null @@ -1,56 +0,0 @@ -import pytest - -from mpt_api_client.resources.accounts.buyers import Buyer -from seed.accounts.buyer import build_buyer_data, create_buyer, seed_buyer -from seed.context import Context - - -@pytest.fixture -def buyer(): - return Buyer({"id": "BUY-123", "name": "Test Buyer"}) - - -def test_build_buyer_data(context: Context): - context["accounts.account.id"] = "ACC-1086-6867" - context["accounts.seller.id"] = "SEL-9999-9999" - expected_data = { - "name": "E2E Seeded Buyer", - "account": { - "id": "ACC-1086-6867", - }, - "contact": { - "firstName": "first", - "lastName": "last", - "email": "created.buyer@example.com", - }, - "address": { - "addressLine1": "123 Main St", - "city": "Los Angeles", - "state": "CA", - "postCode": "12345", - "country": "US", - }, - "sellers": [{"id": "SEL-9999-9999"}], - } - - result = build_buyer_data(context=context) - - assert result == expected_data - - -async def test_create_buyer(mocker, context: Context, operations_client, buyer): - context["accounts.seller.id"] = "SEL-9999-9999" - context["accounts.account.id"] = "ACC-1086-6867" - operations_client.accounts.buyers.create = mocker.AsyncMock(return_value=buyer) - - result = await create_buyer(context, operations_client) - - assert result == buyer - - -async def test_seed_buyer(mocker): - init_resource = mocker.patch("seed.accounts.buyer.init_resource", autospec=True) - - await seed_buyer() # act - - init_resource.assert_awaited_once() diff --git a/tests/seed/accounts/test_licensee.py b/tests/seed/accounts/test_licensee.py deleted file mode 100644 index 7a8e652..0000000 --- a/tests/seed/accounts/test_licensee.py +++ /dev/null @@ -1,79 +0,0 @@ -import pytest - -from mpt_api_client.models.model import Model -from mpt_api_client.resources.accounts.licensees import Licensee -from seed.accounts.licensee import build_licensee_data, create_licensee, seed_licensee -from seed.context import Context - - -@pytest.fixture -def licensee(): - return Licensee({ - "id": "LIC-123", - "name": "E2E Seeded Licensee", - "account": {"id": "ACC-1086-6867"}, - "contact": { - "firstName": "first", - "lastName": "last", - "email": "created.licensee@example.com", - }, - "address": { - "addressLine1": "123 Main St", - "city": "Los Angeles", - "state": "CA", - "postCode": "67890", - "country": "US", - }, - "group": {"id": "UG-123"}, - }) - - -def test_build_licensee_data(context: Context, monkeypatch): - monkeypatch.setenv("CLIENT_ACCOUNT_ID", "ACC-1086-6867") - context["accounts.user_group.id"] = "UG-123" - context.set_resource("accounts.user_group", Model({"id": "UG-123"})) - context["accounts.seller.id"] = "SEL-123" - context["accounts.buyer.id"] = "BUY-123" - context["accounts.account.id"] = "ACC-1086-6867" - expected = { - "name": "E2E Seeded Licensee", - "address": { - "addressLine1": "123 Main St", - "city": "Los Angeles", - "state": "CA", - "postCode": "67890", - "country": "US", - }, - "useBuyerAddress": False, - "seller": {"id": "SEL-123"}, - "buyer": {"id": "BUY-123"}, - "account": {"id": "ACC-1086-6867"}, - "eligibility": {"client": True, "partner": False}, - "groups": [{"id": "UG-123"}], - "type": "Client", - "status": "Enabled", - "defaultLanguage": "en-US", - } - - result = build_licensee_data(context=context) - - assert result == expected - - -async def test_create_licensee(mocker, operations_client, licensee): - create_mock = mocker.AsyncMock(return_value=licensee) - operations_client.accounts.licensees.create = create_mock - mocker.patch("seed.accounts.licensee.build_licensee_data") - - result = await create_licensee(operations_client) - - assert result == licensee - create_mock.assert_awaited_once() - - -async def test_seed_licensee(mocker): - init_resource = mocker.patch("seed.accounts.licensee.init_resource", autospec=True) - - await seed_licensee() # act - - init_resource.assert_awaited_once() diff --git a/tests/seed/accounts/test_module.py b/tests/seed/accounts/test_module.py deleted file mode 100644 index a41cd4b..0000000 --- a/tests/seed/accounts/test_module.py +++ /dev/null @@ -1,65 +0,0 @@ -import pytest - -from mpt_api_client.resources.accounts.modules import AsyncModulesService, Module -from seed.accounts.module import find_module, seed_module - - -class DummyAsyncIterator: - def __init__(self, items): # noqa: WPS110 - self._iterator = iter(items) # noqa: WPS110 - - def __aiter__(self): - return self - - async def __anext__(self): - try: - return next(self._iterator) - except StopIteration as err: - raise StopAsyncIteration from err - - -@pytest.fixture -def module(): - return Module({"id": "MOD-123", "name": "Test Module"}) - - -@pytest.fixture -def modules_service(mocker): - return mocker.Mock(spec=AsyncModulesService) - - -def async_iter(iter_items): - yield from iter_items - - -async def test_find_module(operations_client, module, modules_service, mocker): - operations_client.accounts.modules = modules_service - mocker.patch.object( - operations_client.accounts.modules, "filter", return_value=mocker.AsyncMock() - ) - modules_filter = operations_client.accounts.modules.filter - modules_filter.return_value.iterate = lambda: DummyAsyncIterator([module]) - - result = await find_module(mpt_operations=operations_client) - - assert result == module - - -async def test_find_module_not_found(operations_client, modules_service, mocker): - operations_client.accounts.modules = modules_service - mocker.patch.object( - operations_client.accounts.modules, "filter", return_value=mocker.AsyncMock() - ) - modules_filter = operations_client.accounts.modules.filter - modules_filter.return_value.iterate = lambda: DummyAsyncIterator([]) - - with pytest.raises(ValueError, match=r"Module 'Access Management' not found."): - await find_module(mpt_operations=operations_client) - - -async def test_seed_module(mocker): - init_resource = mocker.patch("seed.accounts.module.init_resource", autospec=True) - - await seed_module() # act - - init_resource.assert_awaited_once() diff --git a/tests/seed/accounts/test_seller.py b/tests/seed/accounts/test_seller.py deleted file mode 100644 index 084d2e2..0000000 --- a/tests/seed/accounts/test_seller.py +++ /dev/null @@ -1,52 +0,0 @@ -import pytest - -from mpt_api_client.resources.accounts.sellers import Seller -from seed.accounts.seller import ( - build_seller_data, - create_seller, - seed_seller, -) - - -@pytest.fixture -def seller(): - return Seller({"id": "SEL-123", "name": "Test Seller"}) - - -def test_build_seller_data(): - external_id = "test-external-id" - seller_data = { - "name": "E2E Seeded Seller", - "address": { - "addressLine1": "123 Main St", - "city": "Los Angeles", - "state": "CA", - "postCode": "12345", - "country": "US", - }, - "currencies": ["USD", "EUR"], - "externalId": external_id, # Must be unique in Marketplace - } - - result = build_seller_data(external_id=external_id) - - assert result == seller_data - - -async def test_create_seller(mocker, operations_client): - seller = Seller({"id": "SEL-123"}) - create_mock = mocker.AsyncMock(return_value=seller) - operations_client.accounts.sellers.create = create_mock - - result = await create_seller(operations_client) - - assert result == seller - create_mock.assert_called_once() - - -async def test_seed_seller(mocker): - init_resource = mocker.patch("seed.accounts.seller.init_resource", autospec=True) - - await seed_seller() # act - - init_resource.assert_awaited_once() diff --git a/tests/seed/accounts/test_user_group.py b/tests/seed/accounts/test_user_group.py deleted file mode 100644 index 86ba815..0000000 --- a/tests/seed/accounts/test_user_group.py +++ /dev/null @@ -1,51 +0,0 @@ -import pytest - -from mpt_api_client.resources.accounts.user_groups import UserGroup -from seed.accounts.user_group import ( - build_user_group_data, - create_user_group, - seed_user_group, -) -from seed.context import Context - - -@pytest.fixture -def user_group(): - return UserGroup({"id": "UG-123", "name": "Test User Group"}) - - -def test_build_user_group_data(context: Context, monkeypatch): - monkeypatch.setenv("CLIENT_ACCOUNT_ID", "ACC-1086-6867") - context["accounts.module.id"] = "MOD-456" - context["accounts.account.id"] = "ACC-1086-6867" - expected_data = { - "name": "E2E Seeded User Group", - "account": {"id": "ACC-1086-6867"}, - "buyers": None, - "logo": "", - "description": "User group for E2E tests", - "modules": [{"id": "MOD-456"}], - } - - result = build_user_group_data(context) - - assert result == expected_data - - -async def test_create_user_group(mocker, operations_client, user_group): - create_mock = mocker.AsyncMock(return_value=user_group) - operations_client.accounts.user_groups.create = create_mock - mocker.patch("seed.accounts.user_group.build_user_group_data") - - result = await create_user_group(operations_client) - - assert result == user_group - create_mock.assert_awaited_once() - - -async def test_seed_user_group(mocker): - init_resource = mocker.patch("seed.accounts.user_group.init_resource", autospec=True) - - await seed_user_group() # act - - init_resource.assert_awaited_once_with("accounts.user_group.id", create_user_group) diff --git a/tests/seed/catalog/__init__.py b/tests/seed/catalog/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/seed/catalog/test_authorization.py b/tests/seed/catalog/test_authorization.py deleted file mode 100644 index 2c2bee6..0000000 --- a/tests/seed/catalog/test_authorization.py +++ /dev/null @@ -1,40 +0,0 @@ -import pytest - -from seed.catalog.authorization import create_authorization, seed_authorization -from seed.context import Context - - -@pytest.fixture -def context_with_data() -> Context: - ctx = Context() - ctx["catalog.product.id"] = "prod-123" - ctx["accounts.seller.id"] = "seller-456" - ctx["accounts.account.id"] = "acct-321" - return ctx - - -async def test_create_authorization(mocker, operations_client, context_with_data): - create_mock = mocker.AsyncMock(return_value={"id": "auth-1"}) - operations_client.catalog.authorizations.create = create_mock - fake_uuid = mocker.Mock(hex="cafebabe12345678") - mocker.patch("uuid.uuid4", return_value=fake_uuid) - - result = await create_authorization(operations_client, context_with_data) - - assert result == {"id": "auth-1"} - args, _ = create_mock.await_args - payload = args[0] - assert payload["product"]["id"] == "prod-123" - assert payload["owner"]["id"] == "seller-456" - assert payload["vendor"]["id"] == "acct-321" - - -async def test_seed_authorization(mocker): - init_resource = mocker.patch( - "seed.catalog.authorization.init_resource", - autospec=True, - ) - - await seed_authorization() - - init_resource.assert_awaited_once_with("catalog.authorization.id", create_authorization) diff --git a/tests/seed/catalog/test_catalog.py b/tests/seed/catalog/test_catalog.py deleted file mode 100644 index adda5c1..0000000 --- a/tests/seed/catalog/test_catalog.py +++ /dev/null @@ -1,18 +0,0 @@ -from unittest.mock import patch - -from seed.catalog.catalog import seed_catalog - - -async def test_seed_catalog() -> None: - with ( - patch("seed.catalog.catalog.seed_product", autospec=True) as seed_product, - patch("seed.catalog.catalog.seed_authorization", autospec=True) as seed_authorization, - patch("seed.catalog.catalog.seed_price_list", autospec=True) as seed_price_list, - patch("seed.catalog.catalog.seed_listing", autospec=True) as seed_listing, - ): - await seed_catalog() # act - - seed_product.assert_awaited_once() - seed_authorization.assert_awaited_once() - seed_price_list.assert_awaited_once() - seed_listing.assert_awaited_once() diff --git a/tests/seed/catalog/test_listing.py b/tests/seed/catalog/test_listing.py deleted file mode 100644 index 2b236cc..0000000 --- a/tests/seed/catalog/test_listing.py +++ /dev/null @@ -1,42 +0,0 @@ -import pytest - -from seed.catalog.listing import create_listing, seed_listing -from seed.context import Context - - -@pytest.fixture -def context_with_data() -> Context: - ctx = Context() - ctx["catalog.product.id"] = "prod-123" - ctx["accounts.seller.id"] = "seller-456" - ctx["catalog.authorization.id"] = "auth-789" - ctx["accounts.account.id"] = "acct-321" - ctx["catalog.price_list.id"] = "pl-654" - return ctx - - -async def test_create_listing(mocker, operations_client, context_with_data): # noqa: WPS218 - create_mock = mocker.AsyncMock(return_value={"id": "lst-1"}) - operations_client.catalog.listings.create = create_mock - - result = await create_listing(operations_client, context_with_data) - - assert result == {"id": "lst-1"} - args, _ = create_mock.await_args - payload = args[0] - assert payload["product"]["id"] == "prod-123" - assert payload["seller"]["id"] == "seller-456" - assert payload["authorization"]["id"] == "auth-789" - assert payload["vendor"]["id"] == "acct-321" - assert payload["priceList"]["id"] == "pl-654" - - -async def test_seed_listing(mocker, context_with_data): - init_resource = mocker.patch( - "seed.catalog.listing.init_resource", - autospec=True, - ) - - await seed_listing() - - init_resource.assert_awaited_once_with("catalog.listing.id", create_listing) diff --git a/tests/seed/catalog/test_price_list.py b/tests/seed/catalog/test_price_list.py deleted file mode 100644 index 722478b..0000000 --- a/tests/seed/catalog/test_price_list.py +++ /dev/null @@ -1,34 +0,0 @@ -import pytest - -from seed.catalog.price_list import create_price_list, seed_price_list -from seed.context import Context - - -@pytest.fixture -def context_with_product(): - ctx = Context() - ctx["catalog.product.id"] = "prod-123" - return ctx - - -async def test_create_price_list(mocker, operations_client, context_with_product): - create_mock = mocker.AsyncMock(return_value={"id": "pl-1"}) - operations_client.catalog.price_lists.create = create_mock - - result = await create_price_list(operations_client, context_with_product) - - assert result == {"id": "pl-1"} - args, _ = create_mock.await_args - payload = args[0] - assert payload["product"]["id"] == "prod-123" - - -async def test_seed_price_list_create(mocker): - init_resource = mocker.patch( - "seed.catalog.price_list.init_resource", - autospec=True, - ) - - await seed_price_list() - - init_resource.assert_awaited_once_with("catalog.price_list.id", create_price_list) diff --git a/tests/seed/catalog/test_product.py b/tests/seed/catalog/test_product.py deleted file mode 100644 index 0d2f777..0000000 --- a/tests/seed/catalog/test_product.py +++ /dev/null @@ -1,166 +0,0 @@ -import pytest - -from mpt_api_client.resources.catalog.products import Product -from seed.catalog.product import ( # noqa: WPS235 - create_document, - create_item_group, - create_parameter, - create_parameter_group, - create_product, - create_product_item, - create_template, - create_terms, - create_terms_variant, - create_unit_of_measure, - publish_product, -) -from seed.context import Context - - -@pytest.fixture -def product(): - return Product({"id": "prod-123", "status": "Draft"}) - - -@pytest.fixture -def context_with_product(): - context = Context() - context["catalog.product.id"] = "prod-123" - return context - - -async def test_publish_product(mocker, vendor_client, operations_client, context_with_product): - product_draft = Product({"id": "prod-123", "status": "Draft"}) - product_pending = Product({"id": "prod-123", "status": "Pending"}) - product_published = Product({"id": "prod-123", "status": "Published"}) - - vendor_client.catalog.products.get = mocker.AsyncMock(return_value=product_draft) - vendor_client.catalog.products.review = mocker.AsyncMock(return_value=product_pending) - operations_client.catalog.products.publish = mocker.AsyncMock(return_value=product_published) - - await publish_product(context_with_product, vendor_client, operations_client) - - vendor_client.catalog.products.get.assert_called_once_with("prod-123") - vendor_client.catalog.products.review.assert_called_once_with("prod-123") - operations_client.catalog.products.publish.assert_called_once_with("prod-123") - - -async def test_create_product(mocker, context: Context, vendor_client, product): - mpt_vendor = vendor_client - mpt_vendor.catalog.products.create = mocker.AsyncMock(return_value=product) - - result = await create_product(mpt_vendor) - - assert result == product - - -async def test_create_template(mocker, vendor_client, context_with_product): - context = context_with_product - - create_mock = mocker.AsyncMock(return_value={"id": "tmpl-1"}) - vendor_client.catalog.products.templates.return_value.create = create_mock - - result = await create_template(context, vendor_client) - - assert result == {"id": "tmpl-1"} - create_mock.assert_awaited_once() - - -async def test_create_terms(mocker, vendor_client, context_with_product): - context = context_with_product - - create_mock = mocker.AsyncMock(return_value={"id": "term-1"}) - vendor_client.catalog.products.terms.return_value.create = create_mock - - result = await create_terms(context, vendor_client) - - assert result == {"id": "term-1"} - create_mock.assert_awaited_once() - - -async def test_create_terms_variant(mocker, vendor_client, context_with_product): - context = context_with_product - context["catalog.product.terms.id"] = "terms-123" - - create_mock = mocker.AsyncMock(return_value={"id": "variant-1"}) - vendor_client.catalog.products.terms.return_value.variants.return_value.create = create_mock - - result = await create_terms_variant(context, vendor_client) - - assert result == {"id": "variant-1"} - - -async def test_create_parameter_group(mocker, vendor_client, context_with_product): - context = context_with_product - - create_mock = mocker.AsyncMock(return_value={"id": "pg-1"}) - vendor_client.catalog.products.parameter_groups.return_value.create = create_mock - - result = await create_parameter_group(context, vendor_client) - - assert result == {"id": "pg-1"} - create_mock.assert_awaited_once() - - -async def test_create_parameter(mocker, vendor_client, context_with_product): - context = context_with_product - context["catalog.product.parameter_group.id"] = "pg-1" - - create_mock = mocker.AsyncMock(return_value={"id": "param-1"}) - vendor_client.catalog.products.parameters.return_value.create = create_mock - - result = await create_parameter(context, vendor_client) - - assert result == {"id": "param-1"} - create_mock.assert_awaited_once() - - -async def test_create_document(mocker, vendor_client, context_with_product): - context = context_with_product - - create_mock = mocker.AsyncMock(return_value={"id": "doc-1"}) - vendor_client.catalog.products.documents.return_value.create = create_mock - - result = await create_document(context, vendor_client) - - assert result == {"id": "doc-1"} - - -async def test_create_item_group(mocker, vendor_client, context_with_product): - context = context_with_product - - create_mock = mocker.AsyncMock(return_value={"id": "ig-1"}) - vendor_client.catalog.products.item_groups.return_value.create = create_mock - - result = await create_item_group(context, vendor_client) - - assert result == {"id": "ig-1"} - args, _ = create_mock.await_args - payload = args[0] - assert payload["product"]["id"] == "prod-123" - - -async def test_create_unit_of_measure(mocker, vendor_client): - create_mock = mocker.AsyncMock(return_value={"id": "uom-1"}) - vendor_client.catalog.units_of_measure.create = create_mock - - result = await create_unit_of_measure(vendor_client) - - assert result == {"id": "uom-1"} - create_mock.assert_awaited_once() - - -async def test_create_product_item(mocker, vendor_client, context_with_product): - context_with_product["catalog.unit.id"] = "unit-1" - context_with_product["catalog.product.item_group.id"] = "ig-1" - - create_mock = mocker.AsyncMock(return_value={"id": "item-1"}) - vendor_client.catalog.items.create = create_mock - result = await create_product_item(context_with_product, vendor_client) - - assert result == {"id": "item-1"} - args, _ = create_mock.await_args - payload = args[0] - assert payload["unit"]["id"] == "unit-1" - assert payload["group"]["id"] == "ig-1" - assert payload["product"]["id"] == "prod-123" diff --git a/tests/seed/conftest.py b/tests/seed/conftest.py deleted file mode 100644 index 7afdda1..0000000 --- a/tests/seed/conftest.py +++ /dev/null @@ -1,35 +0,0 @@ -import io - -import pytest - -from mpt_api_client import AsyncMPTClient -from seed.context import Context - - -def fake_file(): - return io.BytesIO(b"fake data") - - -@pytest.fixture -def context() -> Context: - return Context() - - -@pytest.fixture -def vendor_client(mocker): - return mocker.Mock(spec=AsyncMPTClient) - - -@pytest.fixture -def operations_client(mocker): - return mocker.Mock(spec=AsyncMPTClient) - - -@pytest.fixture -def client_client(mocker): - return mocker.Mock(spec=AsyncMPTClient) - - -@pytest.fixture -def fake_file_factory(): - return fake_file diff --git a/tests/seed/test_context.py b/tests/seed/test_context.py deleted file mode 100644 index a9daf6b..0000000 --- a/tests/seed/test_context.py +++ /dev/null @@ -1,17 +0,0 @@ -import json -from pathlib import Path - -from seed.context import Context, load_context - - -def test_load_context(tmp_path): - context = Context({"keep": "yes", "overwrite": "old"}) - json_data = {"overwrite": "new", "added": 123} - json_file: Path = tmp_path / "context.json" - json_file.write_text(json.dumps(json_data), encoding="utf-8") - - load_context(json_file, context) # act - - assert context["keep"] == "yes" - assert context["overwrite"] == "new" - assert context["added"] == 123 diff --git a/tests/seed/test_helper.py b/tests/seed/test_helper.py deleted file mode 100644 index 21d23e3..0000000 --- a/tests/seed/test_helper.py +++ /dev/null @@ -1,50 +0,0 @@ -import pytest - -from seed.context import Context -from seed.helper import ResourceRequiredError, init_resource, require_context_id - - -def test_require_context_id_returns_value(): - context = Context() - context["catalog.product.id"] = "prod-123" - - result = require_context_id(context, "catalog.product.id", "creating product") - - assert result == "prod-123" - - -def test_require_context_id_raises_when_missing(): - context = Context() - key = "catalog.product.id" - action = "creating product" - - with pytest.raises(ResourceRequiredError) as exc_info: - require_context_id(context, key, action) - - assert exc_info.value.key == key - assert exc_info.value.action == action - assert exc_info.value.context is context - assert str(exc_info.value) == f"Missing required resource '{key}' before {action}." - - -async def test_init_resource_existing_id(mocker): - context = Context() - context["catalog.product.id"] = "prod-123" - factory = mocker.AsyncMock() - - result = await init_resource("catalog.product.id", factory, context) - - assert result == "prod-123" - factory.assert_not_called() - - -async def test_init_resource_creates(mocker): - context = Context() - resource = mocker.Mock(id="new-456") - factory = mocker.AsyncMock(return_value=resource) - - result = await init_resource("catalog.product.id", factory, context) - - assert result == "new-456" - factory.assert_awaited_once() - assert context.get_string("catalog.product.id") == "new-456" diff --git a/tests/seed/test_seed_api.py b/tests/seed/test_seed_api.py deleted file mode 100644 index 6f05917..0000000 --- a/tests/seed/test_seed_api.py +++ /dev/null @@ -1,37 +0,0 @@ -import pathlib - -import pytest - -from seed.context import Context -from seed.seed_api import seed_api - - -@pytest.fixture -def mock_context(mocker): - context = mocker.Mock(spec=Context) - context.load = mocker.Mock() - context.save = mocker.Mock() - return context - - -@pytest.fixture -def context_file_path(tmp_path): - return tmp_path / "context.json" - - -async def test_seed_api_success(mock_context, mocker): - mock_seed_catalog = mocker.patch("seed.seed_api.seed_catalog", autospec=True) - mock_seed_accounts = mocker.patch("seed.seed_api.seed_accounts", autospec=True) - mock_context_file = mocker.patch("seed.seed_api.context_file") - load = mocker.patch("seed.seed_api.load_context") - save = mocker.patch("seed.seed_api.save_context") - - mock_seed_catalog.return_value = None - mock_context_file.return_value = pathlib.Path("test_context.json") - - await seed_api(context=mock_context) - - load.assert_called_once() - mock_seed_catalog.assert_awaited_once() - mock_seed_accounts.assert_awaited_once() - save.assert_called_once()