Add spin session functionality and update game mechanics
- Introduced a new `spin_sessions` table to track user spin activities. - Updated the API to include a new endpoint for spinning games, allowing users to place bets and specify spin counts. - Enhanced game information structure and added validation for bets and spin counts. - Implemented the `Forest Fortune` slot game mechanics, including payline evaluation and scatter functionality. - Updated dependencies in `pyproject.toml` for development and added `httpx` for HTTP requests. - Added unit tests for the new slot mechanics and API endpoints to ensure functionality and reliability.
This commit is contained in:
111
tests/test_spin_api.py
Normal file
111
tests/test_spin_api.py
Normal file
@@ -0,0 +1,111 @@
|
||||
"""API tests for spin endpoint and wallet debit/credit."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import unittest
|
||||
from decimal import Decimal
|
||||
|
||||
from fastapi.testclient import TestClient
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from sqlalchemy.pool import StaticPool
|
||||
|
||||
from app.core.database import Base, get_db
|
||||
from app.main import create_app
|
||||
|
||||
|
||||
class SpinApiTests(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
engine = create_engine(
|
||||
"sqlite://",
|
||||
connect_args={"check_same_thread": False},
|
||||
poolclass=StaticPool,
|
||||
)
|
||||
TestingSession = sessionmaker(bind=engine, autocommit=False, autoflush=False)
|
||||
Base.metadata.create_all(bind=engine)
|
||||
|
||||
def override_get_db():
|
||||
db = TestingSession()
|
||||
try:
|
||||
yield db
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
self.app = create_app()
|
||||
self.app.dependency_overrides[get_db] = override_get_db
|
||||
self.client = TestClient(self.app)
|
||||
self.TestingSession = TestingSession
|
||||
|
||||
login = self.client.post(
|
||||
"/auth/dev-login",
|
||||
json={"telegram_id": 424242, "username": "tester", "first_name": "Test"},
|
||||
)
|
||||
self.assertEqual(login.status_code, 200)
|
||||
token = login.json()["access_token"]
|
||||
self.headers = {"Authorization": f"Bearer {token}"}
|
||||
|
||||
agree = self.client.post("/me/agreement", headers=self.headers)
|
||||
self.assertEqual(agree.status_code, 200)
|
||||
|
||||
deposit = self.client.post("/wallet/deposit", headers=self.headers, json={"amount": 1000})
|
||||
self.assertEqual(deposit.status_code, 200)
|
||||
self.assertEqual(Decimal(deposit.json()["balance"]), Decimal("1000.00"))
|
||||
|
||||
def test_list_games_includes_forest(self) -> None:
|
||||
res = self.client.get("/games")
|
||||
self.assertEqual(res.status_code, 200)
|
||||
slugs = {g["slug"]: g for g in res.json()}
|
||||
self.assertIn("forest-fortune", slugs)
|
||||
self.assertEqual(slugs["forest-fortune"]["status"], "available")
|
||||
self.assertEqual(slugs["forest-fortune"]["max_spin_count"], 1000)
|
||||
|
||||
def test_spin_debit_and_credit(self) -> None:
|
||||
res = self.client.post(
|
||||
"/games/forest-fortune/spin",
|
||||
headers=self.headers,
|
||||
json={"bet": 10, "spin_count": 3},
|
||||
)
|
||||
self.assertEqual(res.status_code, 200, res.text)
|
||||
body = res.json()
|
||||
self.assertEqual(body["spin_count"], 3)
|
||||
self.assertEqual(Decimal(body["total_bet"]), Decimal("30.00"))
|
||||
self.assertEqual(len(body["spins"]), 3)
|
||||
expected = Decimal("1000.00") - Decimal(body["total_bet"]) + Decimal(body["total_win"])
|
||||
self.assertEqual(Decimal(body["balance"]), expected)
|
||||
|
||||
def test_reject_spin_count_over_limit(self) -> None:
|
||||
res = self.client.post(
|
||||
"/games/forest-fortune/spin",
|
||||
headers=self.headers,
|
||||
json={"bet": 1, "spin_count": 1001},
|
||||
)
|
||||
self.assertEqual(res.status_code, 422)
|
||||
|
||||
def test_reject_spin_count_zero_via_validation(self) -> None:
|
||||
res = self.client.post(
|
||||
"/games/forest-fortune/spin",
|
||||
headers=self.headers,
|
||||
json={"bet": 1, "spin_count": 0},
|
||||
)
|
||||
self.assertEqual(res.status_code, 422)
|
||||
|
||||
def test_insufficient_balance(self) -> None:
|
||||
res = self.client.post(
|
||||
"/games/forest-fortune/spin",
|
||||
headers=self.headers,
|
||||
json={"bet": 500, "spin_count": 10},
|
||||
)
|
||||
self.assertEqual(res.status_code, 400)
|
||||
self.assertIn("Insufficient", res.json()["detail"])
|
||||
|
||||
def test_coming_soon_unavailable(self) -> None:
|
||||
res = self.client.post(
|
||||
"/games/raven-reels/spin",
|
||||
headers=self.headers,
|
||||
json={"bet": 1, "spin_count": 1},
|
||||
)
|
||||
self.assertEqual(res.status_code, 503)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user