fix(loyalty): fix wallet service test fixtures and mock paths
Some checks failed
CI / ruff (push) Successful in 10s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has been cancelled

- Add customer_id to card fixtures (NOT NULL constraint)
- Use test_customer shared fixture instead of inline Customer creation
- Fix mock path to target source module for lazy imports

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-24 22:50:16 +01:00
parent a4519035df
commit 56afb9192b

View File

@@ -17,32 +17,19 @@ import pytest
from app.modules.loyalty.models import LoyaltyCard, LoyaltyProgram
from app.modules.loyalty.models.loyalty_program import LoyaltyType
from app.modules.loyalty.services.wallet_service import WalletService
from app.modules.tenancy.models import Merchant
# ============================================================================
# Fixtures
# Uses test_merchant and test_customer from shared fixtures (store_fixtures,
# customer_fixtures) which handle owner_user_id and other required fields.
# ============================================================================
@pytest.fixture
def wt_merchant(db):
"""Create a merchant for wallet tests."""
merchant = Merchant(
name=f"Wallet Test Merchant {uuid.uuid4().hex[:8]}",
contact_email=f"wallet_{uuid.uuid4().hex[:8]}@test.com",
is_active=True,
)
db.add(merchant)
db.commit()
db.refresh(merchant)
return merchant
@pytest.fixture
def wt_program(db, wt_merchant):
def wt_program(db, test_merchant):
"""Create a loyalty program for wallet tests."""
program = LoyaltyProgram(
merchant_id=wt_merchant.id,
merchant_id=test_merchant.id,
loyalty_type=LoyaltyType.POINTS.value,
points_per_euro=10,
welcome_bonus_points=0,
@@ -61,10 +48,10 @@ def wt_program(db, wt_merchant):
@pytest.fixture
def wt_program_with_apple(db, wt_merchant):
def wt_program_with_apple(db, test_merchant):
"""Create a loyalty program with Apple Wallet configured."""
program = LoyaltyProgram(
merchant_id=wt_merchant.id,
merchant_id=test_merchant.id,
loyalty_type=LoyaltyType.POINTS.value,
points_per_euro=10,
welcome_bonus_points=0,
@@ -84,12 +71,12 @@ def wt_program_with_apple(db, wt_merchant):
@pytest.fixture
def wt_card(db, wt_program):
def wt_card(db, wt_program, test_customer):
"""Create a loyalty card for wallet tests."""
card = LoyaltyCard(
merchant_id=wt_program.merchant_id,
program_id=wt_program.id,
customer_id=None,
customer_id=test_customer.id,
card_number=f"WT-{uuid.uuid4().hex[:8].upper()}",
is_active=True,
)
@@ -100,12 +87,12 @@ def wt_card(db, wt_program):
@pytest.fixture
def wt_card_apple(db, wt_program_with_apple):
def wt_card_apple(db, wt_program_with_apple, test_customer):
"""Create a loyalty card for Apple Wallet tests."""
card = LoyaltyCard(
merchant_id=wt_program_with_apple.merchant_id,
program_id=wt_program_with_apple.id,
customer_id=None,
customer_id=test_customer.id,
card_number=f"WTA-{uuid.uuid4().hex[:8].upper()}",
is_active=True,
)
@@ -143,7 +130,7 @@ class TestWalletService:
class TestCreateWalletObjectsGoogle:
"""Tests for Google Wallet object creation during enrollment."""
@patch("app.modules.loyalty.services.wallet_service.google_wallet_service")
@patch("app.modules.loyalty.services.google_wallet_service.google_wallet_service")
def test_google_wallet_object_created_when_configured(
self, mock_gw, db, wt_card
):
@@ -157,7 +144,7 @@ class TestCreateWalletObjectsGoogle:
assert results["google_wallet"] is True
mock_gw.create_object.assert_called_once_with(db, wt_card)
@patch("app.modules.loyalty.services.wallet_service.google_wallet_service")
@patch("app.modules.loyalty.services.google_wallet_service.google_wallet_service")
def test_google_wallet_skipped_when_not_configured(
self, mock_gw, db, wt_card
):
@@ -170,7 +157,7 @@ class TestCreateWalletObjectsGoogle:
assert results["google_wallet"] is False
mock_gw.create_object.assert_not_called()
@patch("app.modules.loyalty.services.wallet_service.google_wallet_service")
@patch("app.modules.loyalty.services.google_wallet_service.google_wallet_service")
def test_google_wallet_failure_does_not_crash(
self, mock_gw, db, wt_card
):
@@ -203,7 +190,7 @@ class TestCreateWalletObjectsApple:
service = WalletService()
with patch(
"app.modules.loyalty.services.wallet_service.google_wallet_service"
"app.modules.loyalty.services.google_wallet_service.google_wallet_service"
) as mock_gw:
mock_gw.is_configured = False
results = service.create_wallet_objects(db, wt_card_apple)
@@ -217,7 +204,7 @@ class TestCreateWalletObjectsApple:
"""Apple serial number not set when program lacks apple_pass_type_id."""
service = WalletService()
with patch(
"app.modules.loyalty.services.wallet_service.google_wallet_service"
"app.modules.loyalty.services.google_wallet_service.google_wallet_service"
) as mock_gw:
mock_gw.is_configured = False
results = service.create_wallet_objects(db, wt_card)
@@ -337,7 +324,7 @@ class TestEnrollmentWalletCreation:
@patch("app.modules.loyalty.services.google_wallet_service.settings")
def test_enrollment_creates_google_wallet_object(
self, mock_settings, db, wt_program, wt_merchant
self, mock_settings, db, wt_program, test_merchant, test_customer
):
"""Full enrollment flow creates Google Wallet class + object in DB."""
from app.modules.loyalty.services.google_wallet_service import (
@@ -355,20 +342,9 @@ class TestEnrollmentWalletCreation:
google_wallet_service._http_client = mock_http
google_wallet_service._credentials = MagicMock()
# Create a test customer
from app.modules.customers.models import Customer
customer = Customer(
email=f"wallet_test_{uuid.uuid4().hex[:8]}@test.com",
first_name="Wallet",
last_name="Test",
is_active=True,
)
db.add(customer)
db.commit()
# Enroll via card_service
from app.modules.loyalty.services.card_service import card_service
card = card_service.enroll_customer(db, customer.id, wt_merchant.id)
card = card_service.enroll_customer(db, test_customer.id, test_merchant.id)
# Verify wallet DB fields are populated
db.refresh(card)
@@ -384,20 +360,12 @@ class TestEnrollmentWalletCreation:
google_wallet_service._http_client = None
google_wallet_service._credentials = None
def test_enrollment_succeeds_without_wallet_config(self, db, wt_program, wt_merchant):
def test_enrollment_succeeds_without_wallet_config(
self, db, wt_program, test_merchant, test_customer
):
"""Enrollment works even when Google Wallet is not configured."""
from app.modules.customers.models import Customer
customer = Customer(
email=f"no_wallet_{uuid.uuid4().hex[:8]}@test.com",
first_name="No",
last_name="Wallet",
is_active=True,
)
db.add(customer)
db.commit()
from app.modules.loyalty.services.card_service import card_service
card = card_service.enroll_customer(db, customer.id, wt_merchant.id)
card = card_service.enroll_customer(db, test_customer.id, test_merchant.id)
db.refresh(card)
assert card.id is not None
@@ -407,25 +375,15 @@ class TestEnrollmentWalletCreation:
@patch("app.modules.loyalty.services.google_wallet_service.settings")
def test_enrollment_with_apple_wallet_sets_serial(
self, mock_settings, db, wt_program_with_apple
self, mock_settings, db, wt_program_with_apple, test_customer
):
"""Enrollment sets apple_serial_number when program has apple_pass_type_id."""
mock_settings.loyalty_google_issuer_id = None
mock_settings.loyalty_google_service_account_json = None
from app.modules.customers.models import Customer
customer = Customer(
email=f"apple_test_{uuid.uuid4().hex[:8]}@test.com",
first_name="Apple",
last_name="Test",
is_active=True,
)
db.add(customer)
db.commit()
from app.modules.loyalty.services.card_service import card_service
card = card_service.enroll_customer(
db, customer.id, wt_program_with_apple.merchant_id
db, test_customer.id, wt_program_with_apple.merchant_id
)
db.refresh(card)