""" Property-based tests for data models. Feature: scm-authentication """ import pytest from hypothesis import given, strategies as st, settings from app.constants.collections import SCM_MERCHANTS_COLLECTION, SCM_staff_COLLECTION # Strategies for generating test data merchant_id_strategy = st.text( alphabet=st.characters(whitelist_categories=("Lu", "Nd"), whitelist_characters="_"), min_size=10, max_size=50 ) business_name_strategy = st.text(min_size=3, max_size=100) email_strategy = st.emails() @pytest.mark.asyncio @settings(max_examples=100) @given( merchant_id1=merchant_id_strategy, merchant_id2=merchant_id_strategy, business_name=business_name_strategy ) async def test_property_associate_id_uniqueness_per_merchant( test_db, merchant_id1, merchant_id2, business_name ): """ Feature: scm-authentication, Property 8: Associate ID uniqueness per merchant For any two staff within the same merchant, their associate_ids should be unique. Validates: Requirements 1.1 """ # Skip if merchant_ids are the same (we want to test within same merchant) if merchant_id1 == merchant_id2: return # Create two staff with different associate_ids in the same merchant staff1 = { "associate_id": f"{merchant_id1}_e001", "merchant_id": merchant_id1, "name": "staff 1", "email": "emp1@test.com", "mobile": "+11111111111", "role_id": "admin", "merchant_type": "retail" } staff2 = { "associate_id": f"{merchant_id1}_e002", "merchant_id": merchant_id1, "name": "staff 2", "email": "emp2@test.com", "mobile": "+12222222222", "role_id": "manager", "merchant_type": "retail" } # Insert both staff await test_db[SCM_staff_COLLECTION].insert_one(staff1) await test_db[SCM_staff_COLLECTION].insert_one(staff2) # Verify both exist count = await test_db[SCM_staff_COLLECTION].count_documents({"merchant_id": merchant_id1}) assert count == 2 # Verify associate_ids are unique staff = await test_db[SCM_staff_COLLECTION].find({"merchant_id": merchant_id1}).to_list(None) associate_ids = [emp["associate_id"] for emp in staff] assert len(associate_ids) == len(set(associate_ids)), "Associate IDs must be unique within a merchant" @pytest.mark.asyncio @settings(max_examples=100) @given( business_name1=business_name_strategy, business_name2=business_name_strategy, merchant_id1=merchant_id_strategy, merchant_id2=merchant_id_strategy ) async def test_property_business_name_uniqueness( test_db, business_name1, business_name2, merchant_id1, merchant_id2 ): """ Feature: scm-authentication, Property 15: Business name uniqueness For any merchant registration attempt, if the business_name already exists in the scm_merchants collection, the system should reject the registration. Validates: Requirements 8.2 """ # Skip if business names are different (we want to test duplicate scenario) if business_name1 != business_name2: return # Skip if merchant_ids are the same if merchant_id1 == merchant_id2: return # Create first merchant with business_name1 merchant1 = { "merchant_id": merchant_id1, "business_name": business_name1, "merchant_type": "retail", "country": "US", "city": "NYC", "area": "Manhattan", "contact_name": "Contact 1", "contact_email": "contact1@test.com", "contact_number": "+11111111111" } await test_db[SCM_MERCHANTS_COLLECTION].insert_one(merchant1) # Verify first merchant exists existing = await test_db[SCM_MERCHANTS_COLLECTION].find_one({"business_name": business_name1}) assert existing is not None # Attempt to create second merchant with same business name should be prevented # In the actual service, this would raise an error # Here we verify that checking for existing business name works duplicate_check = await test_db[SCM_MERCHANTS_COLLECTION].find_one({"business_name": business_name2}) assert duplicate_check is not None, "Duplicate business name should be detected"