# app/modules/loyalty/tests/unit/test_loyalty_onboarding.py """Unit tests for LoyaltyOnboardingProvider.""" import uuid import pytest from app.modules.loyalty.models.loyalty_program import LoyaltyProgram, LoyaltyType from app.modules.loyalty.services.loyalty_onboarding import LoyaltyOnboardingProvider from app.modules.tenancy.models import Merchant, Store, User @pytest.fixture def loy_owner(db): """Create a store owner for loyalty onboarding tests.""" from middleware.auth import AuthManager auth = AuthManager() user = User( email=f"loyonb_{uuid.uuid4().hex[:8]}@test.com", username=f"loyonb_{uuid.uuid4().hex[:8]}", hashed_password=auth.hash_password("pass123"), role="merchant_owner", is_active=True, ) db.add(user) db.commit() db.refresh(user) return user @pytest.fixture def loy_merchant(db, loy_owner): """Create a merchant for loyalty onboarding tests.""" merchant = Merchant( name="Loyalty Onboarding Merchant", owner_user_id=loy_owner.id, contact_email=loy_owner.email, is_active=True, is_verified=True, ) db.add(merchant) db.commit() db.refresh(merchant) return merchant @pytest.fixture def loy_store(db, loy_merchant): """Create a store (no loyalty program) for loyalty onboarding tests.""" uid = uuid.uuid4().hex[:8] store = Store( merchant_id=loy_merchant.id, store_code=f"LOYONB_{uid.upper()}", subdomain=f"loyonb{uid.lower()}", name="Loyalty Onboarding Store", is_active=True, is_verified=True, ) db.add(store) db.commit() db.refresh(store) return store @pytest.mark.unit @pytest.mark.loyalty class TestLoyaltyOnboardingProvider: """Tests for LoyaltyOnboardingProvider.""" def setup_method(self): self.provider = LoyaltyOnboardingProvider() def test_category(self): """Returns 'loyalty' as the onboarding category.""" assert self.provider.onboarding_category == "loyalty" def test_get_onboarding_steps_returns_one_step(self): """Returns exactly one step: create_program.""" steps = self.provider.get_onboarding_steps() assert len(steps) == 1 assert steps[0].key == "loyalty.create_program" assert steps[0].order == 300 def test_incomplete_without_program(self, db, loy_store): """Step is incomplete when merchant has no loyalty programs.""" result = self.provider.is_step_completed( db, loy_store.id, "loyalty.create_program" ) assert result is False def test_complete_with_program(self, db, loy_store, loy_merchant): """Step is complete when merchant has at least one loyalty program.""" program = LoyaltyProgram( merchant_id=loy_merchant.id, loyalty_type=LoyaltyType.STAMPS.value, stamps_target=10, cooldown_minutes=0, max_daily_stamps=10, require_staff_pin=False, card_name="Test Card", card_color="#FF0000", is_active=True, ) db.add(program) db.commit() result = self.provider.is_step_completed( db, loy_store.id, "loyalty.create_program" ) assert result is True def test_nonexistent_store_returns_false(self, db): """Returns False for a store ID that doesn't exist.""" result = self.provider.is_step_completed( db, 999999, "loyalty.create_program" ) assert result is False def test_unknown_step_key_returns_false(self, db, loy_store): """Returns False for an unrecognized step key.""" result = self.provider.is_step_completed( db, loy_store.id, "loyalty.unknown_step" ) assert result is False