""" 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