Files
orion/tests/unit/services/test_company_service.py
Samir Boulahtit 0583dd2cc4 refactor: move letzshop endpoints to marketplace module and add vendor service tests
Move letzshop-related functionality from tenancy to marketplace module:
- Move admin letzshop routes to marketplace/routes/api/admin_letzshop.py
- Move letzshop schemas to marketplace/schemas/letzshop.py
- Remove letzshop code from tenancy module (admin_vendors, vendor_service)
- Update model exports and imports

Add comprehensive unit tests for vendor services:
- test_company_service.py: Company management operations
- test_platform_service.py: Platform management operations
- test_vendor_domain_service.py: Vendor domain operations
- test_vendor_team_service.py: Vendor team management

Update module definitions:
- billing, messaging, payments: Minor definition updates

Add architecture proposals documentation:
- Module dependency redesign session notes
- Decouple modules implementation plan
- Module decoupling proposal

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 19:25:00 +01:00

356 lines
12 KiB
Python

# tests/unit/services/test_company_service.py
"""Unit tests for CompanyService."""
import uuid
import pytest
from app.modules.tenancy.exceptions import CompanyNotFoundException, UserNotFoundException
from app.modules.tenancy.services.company_service import company_service
from app.modules.tenancy.models import Company
from app.modules.tenancy.schemas.company import (
CompanyCreate,
CompanyUpdate,
CompanyTransferOwnership,
)
# =============================================================================
# FIXTURES
# =============================================================================
@pytest.fixture
def unverified_company(db, test_user):
"""Create an unverified test company."""
unique_id = str(uuid.uuid4())[:8]
company = Company(
name=f"Unverified Company {unique_id}",
owner_user_id=test_user.id,
contact_email=f"unverified{unique_id}@company.com",
is_active=True,
is_verified=False,
)
db.add(company)
db.commit()
db.refresh(company)
return company
@pytest.fixture
def inactive_company(db, test_user):
"""Create an inactive test company."""
unique_id = str(uuid.uuid4())[:8]
company = Company(
name=f"Inactive Company {unique_id}",
owner_user_id=test_user.id,
contact_email=f"inactive{unique_id}@company.com",
is_active=False,
is_verified=True,
)
db.add(company)
db.commit()
db.refresh(company)
return company
# =============================================================================
# CREATE TESTS
# =============================================================================
@pytest.mark.unit
@pytest.mark.tenancy
class TestCompanyServiceCreate:
"""Test suite for company creation."""
def test_create_company_with_new_owner(self, db):
"""Test creating a company with a new owner user."""
unique_id = str(uuid.uuid4())[:8]
company_data = CompanyCreate(
name=f"New Company {unique_id}",
owner_email=f"newowner{unique_id}@example.com",
contact_email=f"contact{unique_id}@company.com",
description="A new test company",
)
company, owner, temp_password = company_service.create_company_with_owner(
db, company_data
)
db.commit()
assert company is not None
assert company.name == f"New Company {unique_id}"
assert company.is_active is True
assert company.is_verified is False
assert owner is not None
assert owner.email == f"newowner{unique_id}@example.com"
assert temp_password is not None # New user gets temp password
def test_create_company_with_existing_owner(self, db, test_user):
"""Test creating a company with an existing user as owner."""
unique_id = str(uuid.uuid4())[:8]
company_data = CompanyCreate(
name=f"Existing Owner Company {unique_id}",
owner_email=test_user.email,
contact_email=f"contact{unique_id}@company.com",
)
company, owner, temp_password = company_service.create_company_with_owner(
db, company_data
)
db.commit()
assert company is not None
assert owner.id == test_user.id
assert temp_password is None # Existing user doesn't get new password
# =============================================================================
# READ TESTS
# =============================================================================
@pytest.mark.unit
@pytest.mark.tenancy
class TestCompanyServiceRead:
"""Test suite for reading companies."""
def test_get_company_by_id_success(self, db, test_company):
"""Test getting a company by ID."""
company = company_service.get_company_by_id(db, test_company.id)
assert company is not None
assert company.id == test_company.id
assert company.name == test_company.name
def test_get_company_by_id_not_found(self, db):
"""Test getting a non-existent company raises exception."""
with pytest.raises(CompanyNotFoundException) as exc_info:
company_service.get_company_by_id(db, 99999)
assert "99999" in str(exc_info.value)
def test_get_companies_paginated(self, db, test_company, other_company):
"""Test getting paginated list of companies."""
companies, total = company_service.get_companies(db, skip=0, limit=10)
assert len(companies) >= 2
assert total >= 2
def test_get_companies_with_search(self, db, test_company):
"""Test searching companies by name."""
# Get the unique part of the company name
search_term = test_company.name.split()[0] # "Test"
companies, total = company_service.get_companies(
db, skip=0, limit=100, search=search_term
)
assert len(companies) >= 1
assert any(c.id == test_company.id for c in companies)
def test_get_companies_filter_by_active(self, db, test_company, inactive_company):
"""Test filtering companies by active status."""
active_companies, _ = company_service.get_companies(
db, skip=0, limit=100, is_active=True
)
inactive_companies, _ = company_service.get_companies(
db, skip=0, limit=100, is_active=False
)
assert all(c.is_active for c in active_companies)
assert all(not c.is_active for c in inactive_companies)
def test_get_companies_filter_by_verified(self, db, test_company, unverified_company):
"""Test filtering companies by verified status."""
verified_companies, _ = company_service.get_companies(
db, skip=0, limit=100, is_verified=True
)
unverified_companies, _ = company_service.get_companies(
db, skip=0, limit=100, is_verified=False
)
assert all(c.is_verified for c in verified_companies)
assert all(not c.is_verified for c in unverified_companies)
# =============================================================================
# UPDATE TESTS
# =============================================================================
@pytest.mark.unit
@pytest.mark.tenancy
class TestCompanyServiceUpdate:
"""Test suite for updating companies."""
def test_update_company_success(self, db, test_company):
"""Test updating company information."""
unique_id = str(uuid.uuid4())[:8]
update_data = CompanyUpdate(
name=f"Updated Company {unique_id}",
description="Updated description",
)
updated = company_service.update_company(db, test_company.id, update_data)
db.commit()
assert updated.name == f"Updated Company {unique_id}"
assert updated.description == "Updated description"
def test_update_company_partial(self, db, test_company):
"""Test partial update of company."""
original_name = test_company.name
update_data = CompanyUpdate(description="Only description updated")
updated = company_service.update_company(db, test_company.id, update_data)
db.commit()
assert updated.name == original_name # Name unchanged
assert updated.description == "Only description updated"
def test_update_company_not_found(self, db):
"""Test updating non-existent company raises exception."""
update_data = CompanyUpdate(name="New Name")
with pytest.raises(CompanyNotFoundException):
company_service.update_company(db, 99999, update_data)
# =============================================================================
# DELETE TESTS
# =============================================================================
@pytest.mark.unit
@pytest.mark.tenancy
class TestCompanyServiceDelete:
"""Test suite for deleting companies."""
def test_delete_company_success(self, db, test_user):
"""Test deleting a company."""
# Create a company to delete
unique_id = str(uuid.uuid4())[:8]
company = Company(
name=f"To Delete {unique_id}",
owner_user_id=test_user.id,
contact_email=f"delete{unique_id}@company.com",
is_active=True,
)
db.add(company)
db.commit()
company_id = company.id
# Delete it
company_service.delete_company(db, company_id)
db.commit()
# Verify it's gone
with pytest.raises(CompanyNotFoundException):
company_service.get_company_by_id(db, company_id)
def test_delete_company_not_found(self, db):
"""Test deleting non-existent company raises exception."""
with pytest.raises(CompanyNotFoundException):
company_service.delete_company(db, 99999)
# =============================================================================
# TOGGLE TESTS
# =============================================================================
@pytest.mark.unit
@pytest.mark.tenancy
class TestCompanyServiceToggle:
"""Test suite for toggling company status."""
def test_toggle_verification_on(self, db, unverified_company):
"""Test setting verification to True."""
result = company_service.toggle_verification(db, unverified_company.id, True)
db.commit()
assert result.is_verified is True
def test_toggle_verification_off(self, db, test_company):
"""Test setting verification to False."""
result = company_service.toggle_verification(db, test_company.id, False)
db.commit()
assert result.is_verified is False
def test_toggle_active_on(self, db, inactive_company):
"""Test setting active status to True."""
result = company_service.toggle_active(db, inactive_company.id, True)
db.commit()
assert result.is_active is True
def test_toggle_active_off(self, db, test_company):
"""Test setting active status to False."""
result = company_service.toggle_active(db, test_company.id, False)
db.commit()
assert result.is_active is False
# =============================================================================
# OWNERSHIP TRANSFER TESTS
# =============================================================================
@pytest.mark.unit
@pytest.mark.tenancy
class TestCompanyServiceOwnershipTransfer:
"""Test suite for company ownership transfer."""
def test_transfer_ownership_success(self, db, test_company, other_user):
"""Test successful ownership transfer."""
original_owner_id = test_company.owner_user_id
transfer_data = CompanyTransferOwnership(
new_owner_user_id=other_user.id,
transfer_reason="Testing ownership transfer",
)
company, old_owner, new_owner = company_service.transfer_ownership(
db, test_company.id, transfer_data
)
db.commit()
assert company.owner_user_id == other_user.id
assert old_owner.id == original_owner_id
assert new_owner.id == other_user.id
def test_transfer_ownership_to_same_owner_fails(self, db, test_company, test_user):
"""Test transfer to same owner raises error."""
transfer_data = CompanyTransferOwnership(
new_owner_user_id=test_user.id,
transfer_reason="This should fail",
)
with pytest.raises(ValueError) as exc_info:
company_service.transfer_ownership(db, test_company.id, transfer_data)
assert "current owner" in str(exc_info.value).lower()
def test_transfer_ownership_to_nonexistent_user_fails(self, db, test_company):
"""Test transfer to non-existent user raises exception."""
transfer_data = CompanyTransferOwnership(
new_owner_user_id=99999,
transfer_reason="This should fail",
)
with pytest.raises(UserNotFoundException):
company_service.transfer_ownership(db, test_company.id, transfer_data)
def test_transfer_ownership_nonexistent_company_fails(self, db, other_user):
"""Test transfer on non-existent company raises exception."""
transfer_data = CompanyTransferOwnership(
new_owner_user_id=other_user.id,
transfer_reason="This should fail",
)
with pytest.raises(CompanyNotFoundException):
company_service.transfer_ownership(db, 99999, transfer_data)