Files
xiaoxia-saas/tests/unit/test_subscription_use_case.py
T
Xiaoxia AI b79d6718d6
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 21s
Deploy / Deploy Production (push) Has been cancelled
Deploy / Deploy Staging (push) Has been cancelled
style: normalize python formatting gates
2026-06-21 06:52:19 +08:00

355 lines
10 KiB
Python

"""
Subscription 管理 Use Case 测试
"""
from unittest.mock import Mock
import pytest
from packages.application.workspace.subscription_use_case import (
CancelSubscriptionRequest,
CancelSubscriptionUseCase,
UpgradeSubscriptionRequest,
UpgradeSubscriptionUseCase,
)
from packages.domain.entities import Workspace, WorkspaceMember, WorkspaceMemberRole
class TestUpgradeSubscriptionUseCase:
"""升级订阅测试"""
@pytest.fixture
def mock_workspace_repo(self):
repo = Mock()
repo.find_by_id = Mock(return_value=None)
repo.save = Mock()
return repo
@pytest.fixture
def mock_member_repo(self):
repo = Mock()
repo.find_by_workspace_and_user = Mock(return_value=None)
return repo
@pytest.fixture
def use_case(self, mock_workspace_repo, mock_member_repo):
return UpgradeSubscriptionUseCase(
workspace_repository=mock_workspace_repo,
workspace_member_repository=mock_member_repo,
)
def test_upgrade_from_free_to_pro(
self,
use_case,
mock_workspace_repo,
mock_member_repo,
):
"""测试从 Free 升级到 Pro"""
workspace = Workspace(
id="workspace-123",
name="Test Workspace",
owner_user_id="owner-id",
subscription_plan="free",
)
mock_workspace_repo.find_by_id.return_value = workspace
owner_member = WorkspaceMember(
id="member-1",
workspace_id="workspace-123",
user_id="owner-id",
role=WorkspaceMemberRole.OWNER,
)
mock_member_repo.find_by_workspace_and_user.return_value = owner_member
request = UpgradeSubscriptionRequest(
workspace_id="workspace-123",
requester_user_id="owner-id",
new_plan="pro",
)
response, error = use_case.execute(request)
assert error is None
assert response is not None
assert response.old_plan == "free"
assert response.new_plan == "pro"
assert response.max_projects == 999999
assert response.max_storage_gb == 100
# 验证更新了 workspace
assert workspace.subscription_plan == "pro"
assert workspace.max_projects == 999999
assert workspace.subscription_expires_at is not None
def test_upgrade_from_pro_to_enterprise(
self,
use_case,
mock_workspace_repo,
mock_member_repo,
):
"""测试从 Pro 升级到 Enterprise"""
workspace = Workspace(
id="workspace-123",
name="Test Workspace",
owner_user_id="owner-id",
subscription_plan="pro",
max_projects=999999,
max_storage_gb=100,
)
mock_workspace_repo.find_by_id.return_value = workspace
owner_member = WorkspaceMember(
id="member-1",
workspace_id="workspace-123",
user_id="owner-id",
role=WorkspaceMemberRole.OWNER,
)
mock_member_repo.find_by_workspace_and_user.return_value = owner_member
request = UpgradeSubscriptionRequest(
workspace_id="workspace-123",
requester_user_id="owner-id",
new_plan="enterprise",
)
response, error = use_case.execute(request)
assert error is None
assert response is not None
assert response.old_plan == "pro"
assert response.new_plan == "enterprise"
assert response.max_storage_gb == 1000
def test_upgrade_cannot_downgrade(
self,
use_case,
mock_workspace_repo,
mock_member_repo,
):
"""测试不能降级"""
workspace = Workspace(
id="workspace-123",
name="Test Workspace",
owner_user_id="owner-id",
subscription_plan="pro",
)
mock_workspace_repo.find_by_id.return_value = workspace
owner_member = WorkspaceMember(
id="member-1",
workspace_id="workspace-123",
user_id="owner-id",
role=WorkspaceMemberRole.OWNER,
)
mock_member_repo.find_by_workspace_and_user.return_value = owner_member
request = UpgradeSubscriptionRequest(
workspace_id="workspace-123",
requester_user_id="owner-id",
new_plan="free",
)
response, error = use_case.execute(request)
assert response is None
assert "Cannot downgrade" in error
def test_upgrade_already_on_plan(
self,
use_case,
mock_workspace_repo,
mock_member_repo,
):
"""测试已经是该计划"""
workspace = Workspace(
id="workspace-123",
name="Test Workspace",
owner_user_id="owner-id",
subscription_plan="pro",
)
mock_workspace_repo.find_by_id.return_value = workspace
owner_member = WorkspaceMember(
id="member-1",
workspace_id="workspace-123",
user_id="owner-id",
role=WorkspaceMemberRole.OWNER,
)
mock_member_repo.find_by_workspace_and_user.return_value = owner_member
request = UpgradeSubscriptionRequest(
workspace_id="workspace-123",
requester_user_id="owner-id",
new_plan="pro",
)
response, error = use_case.execute(request)
assert response is None
assert "already on pro plan" in error
def test_upgrade_only_owner_can_upgrade(
self,
use_case,
mock_workspace_repo,
mock_member_repo,
):
"""测试只有 Owner 可以升级"""
workspace = Workspace(
id="workspace-123",
name="Test Workspace",
owner_user_id="owner-id",
subscription_plan="free",
)
mock_workspace_repo.find_by_id.return_value = workspace
admin_member = WorkspaceMember(
id="member-1",
workspace_id="workspace-123",
user_id="admin-id",
role=WorkspaceMemberRole.ADMIN,
)
mock_member_repo.find_by_workspace_and_user.return_value = admin_member
request = UpgradeSubscriptionRequest(
workspace_id="workspace-123",
requester_user_id="admin-id",
new_plan="pro",
)
response, error = use_case.execute(request)
assert response is None
assert "Only workspace owner" in error
class TestCancelSubscriptionUseCase:
"""取消订阅测试"""
@pytest.fixture
def mock_workspace_repo(self):
repo = Mock()
repo.find_by_id = Mock(return_value=None)
repo.save = Mock()
return repo
@pytest.fixture
def mock_member_repo(self):
repo = Mock()
repo.find_by_workspace_and_user = Mock(return_value=None)
return repo
@pytest.fixture
def use_case(self, mock_workspace_repo, mock_member_repo):
return CancelSubscriptionUseCase(
workspace_repository=mock_workspace_repo,
workspace_member_repository=mock_member_repo,
)
def test_cancel_subscription_success(
self,
use_case,
mock_workspace_repo,
mock_member_repo,
):
"""测试取消订阅成功"""
workspace = Workspace(
id="workspace-123",
name="Test Workspace",
owner_user_id="owner-id",
subscription_plan="pro",
max_projects=999999,
max_storage_gb=100,
)
mock_workspace_repo.find_by_id.return_value = workspace
owner_member = WorkspaceMember(
id="member-1",
workspace_id="workspace-123",
user_id="owner-id",
role=WorkspaceMemberRole.OWNER,
)
mock_member_repo.find_by_workspace_and_user.return_value = owner_member
request = CancelSubscriptionRequest(
workspace_id="workspace-123",
requester_user_id="owner-id",
)
success, error = use_case.execute(request)
assert success is True
assert error is None
# 验证降级到 free
assert workspace.subscription_plan == "free"
assert workspace.max_projects == 3
assert workspace.max_storage_gb == 10
assert workspace.subscription_expires_at is None
def test_cancel_already_free(
self,
use_case,
mock_workspace_repo,
mock_member_repo,
):
"""测试已经是免费计划"""
workspace = Workspace(
id="workspace-123",
name="Test Workspace",
owner_user_id="owner-id",
subscription_plan="free",
)
mock_workspace_repo.find_by_id.return_value = workspace
owner_member = WorkspaceMember(
id="member-1",
workspace_id="workspace-123",
user_id="owner-id",
role=WorkspaceMemberRole.OWNER,
)
mock_member_repo.find_by_workspace_and_user.return_value = owner_member
request = CancelSubscriptionRequest(
workspace_id="workspace-123",
requester_user_id="owner-id",
)
success, error = use_case.execute(request)
assert success is False
assert "already on free plan" in error
def test_cancel_only_owner_can_cancel(
self,
use_case,
mock_workspace_repo,
mock_member_repo,
):
"""测试只有 Owner 可以取消"""
workspace = Workspace(
id="workspace-123",
name="Test Workspace",
owner_user_id="owner-id",
subscription_plan="pro",
)
mock_workspace_repo.find_by_id.return_value = workspace
admin_member = WorkspaceMember(
id="member-1",
workspace_id="workspace-123",
user_id="admin-id",
role=WorkspaceMemberRole.ADMIN,
)
mock_member_repo.find_by_workspace_and_user.return_value = admin_member
request = CancelSubscriptionRequest(
workspace_id="workspace-123",
requester_user_id="admin-id",
)
success, error = use_case.execute(request)
assert success is False
assert "Only workspace owner" in error