async def test_failed_wallet_enroll_usecase(
    test_db, user_factory, wallet_factory, wallet_repository_mock
):
    """Test failed wallet enroll usecase. (enroll error)"""

    base_user = user_factory.create()
    wallet_factory.create(user=base_user)

    wallet_repository_mock.enroll.side_effect = [ValueError]

    tx_manager = SQLTransactionManager(db=test_db)
    user_repo = UserRepository(db=test_db)
    user = await user_repo.get_by_id(user_id=base_user.id)
    # wallet_repo = WalletRepository(db=test_db)
    wallet_operation_repo = WalletOperationRepository(db=test_db)

    usecase = WalletUsecase(
        tx_manager=tx_manager,
        user_repo=user_repo,
        wallet_repo=wallet_repository_mock,
        wallet_operation_repo=wallet_operation_repo,
    )
    with pytest.raises(ValueError):
        await usecase.enroll(user_id=user.id, amount=Decimal("10.0"))

    new_user = await user_repo.get_by_id(user_id=user.id)
    assert new_user.balance == user.balance
async def test_failed_wallet_transfer_usecase_user_none(
    test_db, user_factory, wallet_factory, user_repository_mock
):
    """Test failed wallet enroll usecase. (user is none)"""

    base_user_1 = user_factory.create()
    wallet_1 = wallet_factory.create(user=base_user_1)

    base_user_2 = user_factory.create()
    wallet_2 = wallet_factory.create(user=base_user_2)

    tx_manager = SQLTransactionManager(db=test_db)
    user_repo = UserRepository(db=test_db)
    user_repository_mock.get_by_wallet_id.return_value = None
    wallet_repo = WalletRepository(db=test_db)
    wallet_operation_repo = WalletOperationRepository(db=test_db)

    usecase = WalletUsecase(
        tx_manager=tx_manager,
        user_repo=user_repository_mock,
        wallet_repo=wallet_repo,
        wallet_operation_repo=wallet_operation_repo,
    )
    with pytest.raises(UserDoesNotExist):
        await usecase.transfer(
            source_wallet_id=wallet_1.id,
            destination_wallet_id=wallet_2.id,
            amount=Decimal("10.0"),
        )
    new_user = await user_repo.get_by_id(base_user_1.id)
    new_wallet_2 = await wallet_repo.get_by_id(wallet_id=wallet_2.id)
    assert new_user.balance == wallet_1.balance
    assert new_wallet_2.balance == wallet_2.balance
async def test_failed_wallet_transfer_usecase_transfer(
    test_db, user_factory, wallet_factory, wallet_repository_mock
):
    """Test failed wallet enroll usecase (transfer error)."""

    base_user_1 = user_factory.create()
    wallet_1 = wallet_factory.create(user=base_user_1)

    base_user_2 = user_factory.create()
    wallet_2 = wallet_factory.create(user=base_user_2)

    tx_manager = SQLTransactionManager(db=test_db)
    user_repo = UserRepository(db=test_db)
    wallet_repo = WalletRepository(db=test_db)
    wallet_repository_mock.get_by_id.side_effect = [wallet_1, wallet_2]
    wallet_repository_mock.transfer.side_effect = [ValueError("Transfer error")]
    wallet_operation_repo = WalletOperationRepository(db=test_db)

    usecase = WalletUsecase(
        tx_manager=tx_manager,
        user_repo=user_repo,
        wallet_repo=wallet_repository_mock,
        wallet_operation_repo=wallet_operation_repo,
    )
    with pytest.raises(ValueError):
        await usecase.transfer(
            source_wallet_id=wallet_1.id,
            destination_wallet_id=wallet_2.id,
            amount=Decimal("10.0"),
        )
    new_user = await user_repo.get_by_id(base_user_1.id)
    new_wallet_2 = await wallet_repo.get_by_id(wallet_id=wallet_2.id)
    assert new_user.balance == wallet_1.balance
    assert new_wallet_2.balance == wallet_2.balance
def run_app():
    """Run application instance"""

    _db = get_db()
    tx_manager = SQLTransactionManager(db=_db)
    user_repo = UserRepository(db=_db)
    wallet_repo = WalletRepository(db=_db)
    wallet_operation_repo = WalletOperationRepository(db=_db)
    user_usecase = UserUsecase(
        tx_manager=tx_manager,
        user_repo=user_repo,
        wallet_repo=wallet_repo,
        wallet_operation_repo=wallet_operation_repo,
    )
    wallet_usecase = WalletUsecase(
        tx_manager=tx_manager,
        user_repo=user_repo,
        wallet_repo=wallet_repo,
        wallet_operation_repo=wallet_operation_repo,
    )
    app = init_app(
        connect_db=connect_db,
        disconnect_db=disconnect_db,
        router=api_router,
        user_usecase=user_usecase,
        wallet_usecase=wallet_usecase,
    )
    return app
async def test_success_wallet_transfer_usecase(test_db, user_factory, wallet_factory):
    """Test success wallet enroll usecase."""

    base_user_1 = user_factory.create()
    wallet_1 = wallet_factory.create(user=base_user_1)

    base_user_2 = user_factory.create()
    wallet_2 = wallet_factory.create(user=base_user_2)

    tx_manager = SQLTransactionManager(db=test_db)
    user_repo = UserRepository(db=test_db)
    wallet_repo = WalletRepository(db=test_db)
    wallet_operation_repo = WalletOperationRepository(db=test_db)

    wo_count = await test_db.execute("select count(*) from wallet_operations;")

    usecase = WalletUsecase(
        tx_manager=tx_manager,
        user_repo=user_repo,
        wallet_repo=wallet_repo,
        wallet_operation_repo=wallet_operation_repo,
    )
    new_user = await usecase.transfer(
        source_wallet_id=wallet_1.id,
        destination_wallet_id=wallet_2.id,
        amount=Decimal("10.0"),
    )
    new_wo_count = await test_db.execute("select count(*) from wallet_operations;")
    new_wallet_2 = await wallet_repo.get_by_id(wallet_id=wallet_2.id)
    assert new_user.balance == wallet_1.balance - Decimal("10.0")
    assert new_wallet_2.balance == wallet_2.balance + Decimal("10.0")
    assert new_wo_count == wo_count + 2
async def client(test_db_instance) -> AsyncGenerator:
    """Client fixture for API tests."""

    test_db = test_db_instance
    tx_manager = SQLTransactionManager(db=test_db)
    user_repo = UserRepository(db=test_db)
    wallet_repo = WalletRepository(db=test_db)
    wallet_operation_repo = WalletOperationRepository(db=test_db)
    user_usecase = UserUsecase(
        tx_manager=tx_manager,
        user_repo=user_repo,
        wallet_repo=wallet_repo,
        wallet_operation_repo=wallet_operation_repo,
    )
    wallet_usecase = WalletUsecase(
        tx_manager=tx_manager,
        user_repo=user_repo,
        wallet_repo=wallet_repo,
        wallet_operation_repo=wallet_operation_repo,
    )
    app = init_app(
        connect_db=connect_db,
        disconnect_db=disconnect_db,
        router=api_router,
        user_usecase=user_usecase,
        wallet_usecase=wallet_usecase,
    )
    async with AsyncClient(
            app=app,
            base_url="http://testserver",
            headers={"Content-Type": "application/json"},
    ) as client_data:
        yield client_data
async def test_failed_user_create_usecase_user_retrieve(
        test_db, user_repository_mock, user_factory):
    """Test failed user create usecase. (wallet operation was not created)"""

    user = user_factory.create()
    user_repository_mock.create.return_value = user.id
    user_repository_mock.get_by_id.side_effect = [
        ValueError("Error database connection")
    ]

    tx_manager = SQLTransactionManager(db=test_db)
    wallet_repo = WalletRepository(db=test_db)
    wallet_operation_repo = WalletOperationRepository(db=test_db)

    usecase = UserUsecase(
        tx_manager=tx_manager,
        user_repo=user_repository_mock,
        wallet_repo=wallet_repo,
        wallet_operation_repo=wallet_operation_repo,
    )
    users_count = await test_db.execute("select count(*) from users")
    wallets_count = await test_db.execute("select count(*) from wallets")
    with pytest.raises(ValueError):
        await usecase.create("*****@*****.**")

    new_users_count = await test_db.execute("select count(*) from users")
    new_wallets_count = await test_db.execute("select count(*) from wallets")
    assert users_count == new_users_count
    assert wallets_count == new_wallets_count
async def test_failed_user_create_usecase_wallet_operation(
        test_db, wallet_operation_repository_mock):
    """Test failed user create usecase. (wallet operation was not created)"""

    wallet_operation_repository_mock.create.side_effect = [
        ValueError("wallet operation was not created")
    ]
    tx_manager = SQLTransactionManager(db=test_db)
    user_repo = UserRepository(db=test_db)
    wallet_repo = WalletRepository(db=test_db)

    usecase = UserUsecase(
        tx_manager=tx_manager,
        user_repo=user_repo,
        wallet_repo=wallet_repo,
        wallet_operation_repo=wallet_operation_repository_mock,
    )
    users_count = await test_db.execute("select count(*) from users")
    wallets_count = await test_db.execute("select count(*) from wallets")
    with pytest.raises(ValueError):
        await usecase.create("*****@*****.**")

    new_users_count = await test_db.execute("select count(*) from users")
    new_wallets_count = await test_db.execute("select count(*) from wallets")
    assert users_count == new_users_count
    assert wallets_count == new_wallets_count
async def test_success_user_create_usecase(test_db):
    """Test success user create usecase."""

    tx_manager = SQLTransactionManager(db=test_db)
    user_repo = UserRepository(db=test_db)
    wallet_repo = WalletRepository(db=test_db)
    wallet_operation_repo = WalletOperationRepository(db=test_db)

    usecase = UserUsecase(
        tx_manager=tx_manager,
        user_repo=user_repo,
        wallet_repo=wallet_repo,
        wallet_operation_repo=wallet_operation_repo,
    )

    users_count = await test_db.execute("select count(*) from users")
    wallets_count = await test_db.execute("select count(*) from wallets")
    wo_count = await test_db.execute("select count(*) from wallet_operations")

    user = await usecase.create("*****@*****.**")

    new_users_count = await test_db.execute("select count(*) from users")
    new_wallets_count = await test_db.execute("select count(*) from wallets")
    new_wo_count = await test_db.execute(
        "select count(*) from wallet_operations")

    assert new_users_count == users_count + 1
    assert new_wallets_count == wallets_count + 1
    assert new_wo_count == wo_count + 1

    assert user is not None
async def test_failed_user_create_usecase_user(test_db):
    """Test failed user create usecase. (user was not created)"""

    tx_manager = SQLTransactionManager(db=test_db)
    user_repo = UserRepository(db=test_db)
    wallet_repo = WalletRepository(db=test_db)
    wallet_operation_repo = WalletOperationRepository(db=test_db)

    usecase = UserUsecase(
        tx_manager=tx_manager,
        user_repo=user_repo,
        wallet_repo=wallet_repo,
        wallet_operation_repo=wallet_operation_repo,
    )
    with pytest.raises(ValueError):
        await usecase.create("")
async def test_failed_user_create_usecase_wallet(test_db,
                                                 wallet_repository_mock):
    """Test failed user create usecase. (wallet was not created)"""

    tx_manager = SQLTransactionManager(db=test_db)
    wallet_repository_mock.create.side_effect = [
        ValueError("wallet was not created")
    ]
    user_repo = UserRepository(db=test_db)
    wallet_operation_repo = WalletOperationRepository(db=test_db)

    usecase = UserUsecase(
        tx_manager=tx_manager,
        user_repo=user_repo,
        wallet_repo=wallet_repository_mock,
        wallet_operation_repo=wallet_operation_repo,
    )
    with pytest.raises(ValueError):
        await usecase.create("*****@*****.**")
async def test_success_wallet_enroll_usecase(test_db, user_factory, wallet_factory):
    """Test success wallet enroll usecase."""

    user = user_factory.create()
    wallet = wallet_factory.create(user=user)
    old_balance = wallet.balance

    tx_manager = SQLTransactionManager(db=test_db)
    user_repo = UserRepository(db=test_db)
    wallet_repo = WalletRepository(db=test_db)
    wallet_operation_repo = WalletOperationRepository(db=test_db)

    usecase = WalletUsecase(
        tx_manager=tx_manager,
        user_repo=user_repo,
        wallet_repo=wallet_repo,
        wallet_operation_repo=wallet_operation_repo,
    )
    new_user = await usecase.enroll(user_id=user.id, amount=Decimal("10.0"))
    assert new_user.balance == old_balance + Decimal("10.0")
async def test_failed_wallet_enroll_usecase_get_user(
    test_db, user_factory, wallet_factory, user_repository_mock
):
    """Test failed wallet enroll usecase (user does not exist)"""

    user = user_factory.create()
    wallet_factory.create(user=user)

    tx_manager = SQLTransactionManager(db=test_db)
    user_repository_mock.get_by_id.return_value = None
    wallet_repo = WalletRepository(db=test_db)
    wallet_operation_repo = WalletOperationRepository(db=test_db)

    usecase = WalletUsecase(
        tx_manager=tx_manager,
        user_repo=user_repository_mock,
        wallet_repo=wallet_repo,
        wallet_operation_repo=wallet_operation_repo,
    )
    with pytest.raises(UserDoesNotExist):
        await usecase.enroll(user_id=user.id, amount=Decimal("10.0"))
async def test_failed_wallet_enroll_usecase_get_user_response(
    test_db, user_factory, wallet_factory, user_repository_mock
):
    """Test failed wallet enroll usecase (user was deleted)"""

    base_user = user_factory.create()
    wallet_factory.create(user=base_user)

    tx_manager = SQLTransactionManager(db=test_db)
    user_repo = UserRepository(db=test_db)
    user = await user_repo.get_by_id(user_id=base_user.id)
    user_repository_mock.get_by_id.side_effect = [user, None]
    wallet_repo = WalletRepository(db=test_db)
    wallet_operation_repo = WalletOperationRepository(db=test_db)

    usecase = WalletUsecase(
        tx_manager=tx_manager,
        user_repo=user_repository_mock,
        wallet_repo=wallet_repo,
        wallet_operation_repo=wallet_operation_repo,
    )
    with pytest.raises(UserDoesNotExist):
        await usecase.enroll(user_id=user.id, amount=Decimal("10.0"))