feat: add CLI test client for interactive API testing
This commit is contained in:
168
cli_client.py
Executable file
168
cli_client.py
Executable file
@@ -0,0 +1,168 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Card Game CLI Client - Interactive testing tool for the backend API.
|
||||
"""
|
||||
|
||||
import requests
|
||||
import json
|
||||
import uuid
|
||||
|
||||
BASE_URL = "http://localhost:8000"
|
||||
|
||||
class CardGameClient:
|
||||
def __init__(self):
|
||||
self.token = None
|
||||
self.session = requests.Session()
|
||||
|
||||
def _headers(self):
|
||||
if self.token:
|
||||
return {"Authorization": f"Bearer {self.token}"}
|
||||
return {}
|
||||
|
||||
def _print_response(self, resp, label="Response"):
|
||||
print(f"\n{label} ({resp.status_code}):")
|
||||
try:
|
||||
print(json.dumps(resp.json(), indent=2))
|
||||
except:
|
||||
print(resp.text)
|
||||
|
||||
def register(self, email, password, nickname):
|
||||
resp = self.session.post(f"{BASE_URL}/auth/register", json={
|
||||
"email": email,
|
||||
"password": password,
|
||||
"nickname": nickname
|
||||
})
|
||||
self._print_response(resp, "Register")
|
||||
if resp.status_code == 200:
|
||||
data = resp.json()
|
||||
self.token = data.get("access_token")
|
||||
print("✓ Logged in automatically after registration.")
|
||||
|
||||
def login(self, email, password):
|
||||
resp = self.session.post(f"{BASE_URL}/auth/login", json={
|
||||
"email": email,
|
||||
"password": password
|
||||
})
|
||||
self._print_response(resp, "Login")
|
||||
if resp.status_code == 200:
|
||||
self.token = resp.json()["access_token"]
|
||||
print("✓ Token saved.")
|
||||
|
||||
def me(self):
|
||||
resp = self.session.get(f"{BASE_URL}/me/profile", headers=self._headers())
|
||||
self._print_response(resp, "My Profile")
|
||||
|
||||
resp = self.session.get(f"{BASE_URL}/me/wallet", headers=self._headers())
|
||||
self._print_response(resp, "My Wallet")
|
||||
|
||||
def collection(self):
|
||||
resp = self.session.get(f"{BASE_URL}/me/collection", headers=self._headers())
|
||||
self._print_response(resp, "My Collection")
|
||||
|
||||
def chests(self):
|
||||
resp = self.session.get(f"{BASE_URL}/catalog/chests")
|
||||
self._print_response(resp, "Available Chests")
|
||||
|
||||
def cards(self):
|
||||
resp = self.session.get(f"{BASE_URL}/catalog/cards")
|
||||
self._print_response(resp, "All Cards")
|
||||
|
||||
def open_chest(self, chest_id, idempotency_key=None):
|
||||
headers = self._headers()
|
||||
if idempotency_key:
|
||||
headers["Idempotency-Key"] = idempotency_key
|
||||
else:
|
||||
headers["Idempotency-Key"] = str(uuid.uuid4())
|
||||
|
||||
resp = self.session.post(f"{BASE_URL}/chests/{chest_id}/open", headers=headers)
|
||||
self._print_response(resp, "Chest Open Result")
|
||||
|
||||
def profile(self, nickname):
|
||||
resp = self.session.get(f"{BASE_URL}/profiles/{nickname}")
|
||||
self._print_response(resp, f"Profile: {nickname}")
|
||||
|
||||
def profile_collection(self, nickname):
|
||||
resp = self.session.get(f"{BASE_URL}/profiles/{nickname}/collection")
|
||||
self._print_response(resp, f"Collection: {nickname}")
|
||||
|
||||
def print_help():
|
||||
print("""
|
||||
=== Card Game CLI ===
|
||||
Commands:
|
||||
register <email> <password> <nickname> - Create new account
|
||||
login <email> <password> - Login to existing account
|
||||
me - Show my profile and wallet
|
||||
collection - Show my cards
|
||||
chests - List available chests
|
||||
cards - List all cards in catalog
|
||||
open <chest_id> - Open a chest
|
||||
profile <nickname> - View public profile
|
||||
profile_collection <nickname> - View public collection
|
||||
help - Show this help
|
||||
quit / exit - Exit
|
||||
""")
|
||||
|
||||
def main():
|
||||
client = CardGameClient()
|
||||
print_help()
|
||||
|
||||
while True:
|
||||
try:
|
||||
cmd = input("\n> ").strip()
|
||||
if not cmd:
|
||||
continue
|
||||
|
||||
parts = cmd.split()
|
||||
command = parts[0].lower()
|
||||
args = parts[1:]
|
||||
|
||||
if command in ["quit", "exit", "q"]:
|
||||
print("Goodbye!")
|
||||
break
|
||||
elif command == "help":
|
||||
print_help()
|
||||
elif command == "register":
|
||||
if len(args) < 3:
|
||||
print("Usage: register <email> <password> <nickname>")
|
||||
else:
|
||||
client.register(args[0], args[1], args[2])
|
||||
elif command == "login":
|
||||
if len(args) < 2:
|
||||
print("Usage: login <email> <password>")
|
||||
else:
|
||||
client.login(args[0], args[1])
|
||||
elif command == "me":
|
||||
client.me()
|
||||
elif command == "collection":
|
||||
client.collection()
|
||||
elif command == "chests":
|
||||
client.chests()
|
||||
elif command == "cards":
|
||||
client.cards()
|
||||
elif command == "open":
|
||||
if len(args) < 1:
|
||||
print("Usage: open <chest_id>")
|
||||
else:
|
||||
key = args[1] if len(args) > 1 else None
|
||||
client.open_chest(args[0], key)
|
||||
elif command == "profile":
|
||||
if len(args) < 1:
|
||||
print("Usage: profile <nickname>")
|
||||
else:
|
||||
client.profile(args[0])
|
||||
elif command == "profile_collection":
|
||||
if len(args) < 1:
|
||||
print("Usage: profile_collection <nickname>")
|
||||
else:
|
||||
client.profile_collection(args[0])
|
||||
else:
|
||||
print(f"Unknown command: {command}. Type 'help' for commands.")
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\nGoodbye!")
|
||||
break
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user