First synculous 2 Big-Pickle pass.
This commit is contained in:
2
tests/__init__.py
Normal file
2
tests/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# tests/__init__.py
|
||||
# Test package
|
||||
2
tests/api/__init__.py
Normal file
2
tests/api/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# tests/api/__init__.py
|
||||
# API tests package
|
||||
130
tests/api/test_routine_steps_extended.py
Normal file
130
tests/api/test_routine_steps_extended.py
Normal file
@@ -0,0 +1,130 @@
|
||||
"""
|
||||
Tests for Routine Steps Extended API
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import requests
|
||||
import uuid
|
||||
|
||||
|
||||
@pytest.mark.api
|
||||
class TestRoutineStepsExtended:
|
||||
"""Tests for routine_steps_extended.py endpoints."""
|
||||
|
||||
def test_update_step_instructions_success(self, api_base_url, auth_headers, test_routine_uuid, test_step_uuid, sample_routine_data, sample_step_data, db_helper):
|
||||
"""Test updating step instructions successfully."""
|
||||
# Setup: create routine and step
|
||||
routine = db_helper.create_routine(sample_routine_data)
|
||||
step = db_helper.create_step({**sample_step_data, "routine_id": routine["id"]})
|
||||
|
||||
response = requests.put(
|
||||
f"{api_base_url}/api/routines/{routine['id']}/steps/{step['id']}/instructions",
|
||||
headers=auth_headers,
|
||||
json={"instructions": "New instructions for step"}
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["instructions"] == "New instructions for step"
|
||||
|
||||
def test_update_step_instructions_unauthorized(self, api_base_url, test_routine_uuid, test_step_uuid):
|
||||
"""Test updating step instructions without auth."""
|
||||
response = requests.put(
|
||||
f"{api_base_url}/api/routines/{test_routine_uuid}/steps/{test_step_uuid}/instructions",
|
||||
json={"instructions": "Test"}
|
||||
)
|
||||
|
||||
assert response.status_code == 401
|
||||
|
||||
def test_update_step_instructions_missing_body(self, api_base_url, auth_headers, sample_routine_data, sample_step_data, db_helper):
|
||||
"""Test updating step instructions with missing body."""
|
||||
routine = db_helper.create_routine(sample_routine_data)
|
||||
step = db_helper.create_step({**sample_step_data, "routine_id": routine["id"]})
|
||||
|
||||
response = requests.put(
|
||||
f"{api_base_url}/api/routines/{routine['id']}/steps/{step['id']}/instructions",
|
||||
headers=auth_headers
|
||||
)
|
||||
|
||||
assert response.status_code == 400
|
||||
|
||||
def test_update_step_type_success(self, api_base_url, auth_headers, sample_routine_data, sample_step_data, db_helper):
|
||||
"""Test updating step type successfully."""
|
||||
routine = db_helper.create_routine(sample_routine_data)
|
||||
step = db_helper.create_step({**sample_step_data, "routine_id": routine["id"]})
|
||||
|
||||
response = requests.put(
|
||||
f"{api_base_url}/api/routines/{routine['id']}/steps/{step['id']}/type",
|
||||
headers=auth_headers,
|
||||
json={"step_type": "timer"}
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["step_type"] == "timer"
|
||||
|
||||
def test_update_step_type_invalid_type(self, api_base_url, auth_headers, sample_routine_data, sample_step_data, db_helper):
|
||||
"""Test updating step type with invalid type."""
|
||||
routine = db_helper.create_routine(sample_routine_data)
|
||||
step = db_helper.create_step({**sample_step_data, "routine_id": routine["id"]})
|
||||
|
||||
response = requests.put(
|
||||
f"{api_base_url}/api/routines/{routine['id']}/steps/{step['id']}/type",
|
||||
headers=auth_headers,
|
||||
json={"step_type": "invalid_type"}
|
||||
)
|
||||
|
||||
assert response.status_code == 400
|
||||
|
||||
def test_update_step_type_all_valid_types(self, api_base_url, auth_headers, sample_routine_data, sample_step_data, db_helper):
|
||||
"""Test all valid step types."""
|
||||
routine = db_helper.create_routine(sample_routine_data)
|
||||
step = db_helper.create_step({**sample_step_data, "routine_id": routine["id"]})
|
||||
|
||||
valid_types = ["generic", "timer", "checklist", "meditation", "exercise"]
|
||||
|
||||
for step_type in valid_types:
|
||||
response = requests.put(
|
||||
f"{api_base_url}/api/routines/{routine['id']}/steps/{step['id']}/type",
|
||||
headers=auth_headers,
|
||||
json={"step_type": step_type}
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_update_step_media_success(self, api_base_url, auth_headers, sample_routine_data, sample_step_data, db_helper):
|
||||
"""Test updating step media URL successfully."""
|
||||
routine = db_helper.create_routine(sample_routine_data)
|
||||
step = db_helper.create_step({**sample_step_data, "routine_id": routine["id"]})
|
||||
|
||||
response = requests.put(
|
||||
f"{api_base_url}/api/routines/{routine['id']}/steps/{step['id']}/media",
|
||||
headers=auth_headers,
|
||||
json={"media_url": "https://example.com/audio.mp3"}
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["media_url"] == "https://example.com/audio.mp3"
|
||||
|
||||
def test_update_step_media_empty(self, api_base_url, auth_headers, sample_routine_data, sample_step_data, db_helper):
|
||||
"""Test updating step media with empty URL."""
|
||||
routine = db_helper.create_routine(sample_routine_data)
|
||||
step = db_helper.create_step({**sample_step_data, "routine_id": routine["id"]})
|
||||
|
||||
response = requests.put(
|
||||
f"{api_base_url}/api/routines/{routine['id']}/steps/{step['id']}/media",
|
||||
headers=auth_headers,
|
||||
json={"media_url": ""}
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_update_step_not_found(self, api_base_url, auth_headers, test_routine_uuid):
|
||||
"""Test updating non-existent step."""
|
||||
response = requests.put(
|
||||
f"{api_base_url}/api/routines/{test_routine_uuid}/steps/{uuid.uuid4()}/instructions",
|
||||
headers=auth_headers,
|
||||
json={"instructions": "Test"}
|
||||
)
|
||||
|
||||
assert response.status_code == 404
|
||||
199
tests/conftest.py
Normal file
199
tests/conftest.py
Normal file
@@ -0,0 +1,199 @@
|
||||
"""
|
||||
conftest.py - pytest fixtures and configuration
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import pytest
|
||||
import uuid
|
||||
from datetime import datetime, date
|
||||
|
||||
# Add project root to path
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
# Set test environment variables
|
||||
os.environ.setdefault("DB_HOST", "localhost")
|
||||
os.environ.setdefault("DB_PORT", "5432")
|
||||
os.environ.setdefault("DB_NAME", "app")
|
||||
os.environ.setdefault("DB_USER", "app")
|
||||
os.environ.setdefault("DB_PASS", "app")
|
||||
os.environ.setdefault("JWT_SECRET", "test-secret-key")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_user_uuid():
|
||||
"""Generate a test user UUID."""
|
||||
return str(uuid.uuid4())
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_routine_uuid():
|
||||
"""Generate a test routine UUID."""
|
||||
return str(uuid.uuid4())
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_step_uuid():
|
||||
"""Generate a test step UUID."""
|
||||
return str(uuid.uuid4())
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_session_uuid():
|
||||
"""Generate a test session UUID."""
|
||||
return str(uuid.uuid4())
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_tag_uuid():
|
||||
"""Generate a test tag UUID."""
|
||||
return str(uuid.uuid4())
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_template_uuid():
|
||||
"""Generate a test template UUID."""
|
||||
return str(uuid.uuid4())
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_routine_data(test_user_uuid):
|
||||
"""Sample routine data for testing."""
|
||||
return {
|
||||
"id": str(uuid.uuid4()),
|
||||
"user_uuid": test_user_uuid,
|
||||
"name": "Test Routine",
|
||||
"description": "A test routine",
|
||||
"icon": "test",
|
||||
"created_at": datetime.now(),
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_step_data(test_routine_uuid):
|
||||
"""Sample step data for testing."""
|
||||
return {
|
||||
"id": str(uuid.uuid4()),
|
||||
"routine_id": test_routine_uuid,
|
||||
"name": "Test Step",
|
||||
"instructions": "Do something",
|
||||
"step_type": "generic",
|
||||
"duration_minutes": 5,
|
||||
"media_url": "https://example.com/media.mp3",
|
||||
"position": 1,
|
||||
"created_at": datetime.now(),
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_session_data(test_routine_uuid, test_user_uuid):
|
||||
"""Sample session data for testing."""
|
||||
return {
|
||||
"id": str(uuid.uuid4()),
|
||||
"routine_id": test_routine_uuid,
|
||||
"user_uuid": test_user_uuid,
|
||||
"status": "active",
|
||||
"current_step_index": 0,
|
||||
"created_at": datetime.now(),
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_tag_data():
|
||||
"""Sample tag data for testing."""
|
||||
return {
|
||||
"id": str(uuid.uuid4()),
|
||||
"name": "morning",
|
||||
"color": "#FF0000",
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_template_data():
|
||||
"""Sample template data for testing."""
|
||||
return {
|
||||
"id": str(uuid.uuid4()),
|
||||
"name": "Morning Routine",
|
||||
"description": "Start your day right",
|
||||
"icon": "sun",
|
||||
"created_by_admin": False,
|
||||
"created_at": datetime.now(),
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_auth_header():
|
||||
"""Mock authorization header for testing."""
|
||||
import jwt
|
||||
token = jwt.encode({"sub": str(uuid.uuid4())}, "test-secret-key", algorithm="HS256")
|
||||
return {"Authorization": f"Bearer {token}"}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def api_base_url():
|
||||
"""Base URL for API tests."""
|
||||
return os.environ.get("API_URL", "http://localhost:8080")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def auth_token(test_user_uuid):
|
||||
"""Generate a valid auth token for testing."""
|
||||
import jwt
|
||||
return jwt.encode({"sub": test_user_uuid}, "test-secret-key", algorithm="HS256")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def auth_headers(auth_token):
|
||||
"""Authorization headers with valid token."""
|
||||
return {"Authorization": f"Bearer {auth_token}", "Content-Type": "application/json"}
|
||||
|
||||
|
||||
def pytest_configure(config):
|
||||
"""Configure pytest with custom markers."""
|
||||
config.addinivalue_line("markers", "api: mark test as API test")
|
||||
config.addinivalue_line("markers", "core: mark test as core module test")
|
||||
config.addinivalue_line("markers", "integration: mark test as integration test")
|
||||
config.addinivalue_line("markers", "slow: mark test as slow running")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def db_helper():
|
||||
"""Fixture that provides a DBHelper instance."""
|
||||
import sys
|
||||
import os
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
class DBHelper:
|
||||
def __init__(self):
|
||||
import core.postgres as postgres
|
||||
self.postgres = postgres
|
||||
|
||||
def create_user(self, data=None):
|
||||
if data is None:
|
||||
data = {}
|
||||
user = {
|
||||
"id": data.get("id", str(uuid.uuid4())),
|
||||
"username": data.get("username", f"testuser_{uuid.uuid4().hex[:8]}"),
|
||||
"password_hashed": data.get("password_hashed", "$2b$12$test"),
|
||||
}
|
||||
return self.postgres.insert("users", user)
|
||||
|
||||
def create_routine(self, data):
|
||||
return self.postgres.insert("routines", data)
|
||||
|
||||
def create_step(self, data):
|
||||
return self.postgres.insert("routine_steps", data)
|
||||
|
||||
def create_session(self, data):
|
||||
return self.postgres.insert("routine_sessions", data)
|
||||
|
||||
def create_tag(self, data):
|
||||
return self.postgres.insert("routine_tags", data)
|
||||
|
||||
def create_template(self, data):
|
||||
return self.postgres.insert("routine_templates", data)
|
||||
|
||||
def create_streak(self, data):
|
||||
return self.postgres.insert("routine_streaks", data)
|
||||
|
||||
return DBHelper()
|
||||
2
tests/core/__init__.py
Normal file
2
tests/core/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# tests/core/__init__.py
|
||||
# Core module tests package
|
||||
78
tests/db_helper.py
Normal file
78
tests/db_helper.py
Normal file
@@ -0,0 +1,78 @@
|
||||
"""
|
||||
Database helper for tests - provides fixtures for creating test data
|
||||
"""
|
||||
|
||||
import uuid
|
||||
import pytest
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Add project root to path
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
|
||||
class DBHelper:
|
||||
"""Helper class for creating test data in the database."""
|
||||
|
||||
def __init__(self):
|
||||
import core.postgres as postgres
|
||||
self.postgres = postgres
|
||||
|
||||
def create_user(self, data=None):
|
||||
"""Create a test user."""
|
||||
if data is None:
|
||||
data = {}
|
||||
user = {
|
||||
"id": data.get("id", str(uuid.uuid4())),
|
||||
"username": data.get("username", f"testuser_{uuid.uuid4().hex[:8]}"),
|
||||
"password_hashed": data.get("password_hashed", "$2b$12$test"),
|
||||
}
|
||||
return self.postgres.insert("users", user)
|
||||
|
||||
def create_routine(self, data):
|
||||
"""Create a test routine."""
|
||||
return self.postgres.insert("routines", data)
|
||||
|
||||
def create_step(self, data):
|
||||
"""Create a test routine step."""
|
||||
return self.postgres.insert("routine_steps", data)
|
||||
|
||||
def create_session(self, data):
|
||||
"""Create a test routine session."""
|
||||
return self.postgres.insert("routine_sessions", data)
|
||||
|
||||
def create_tag(self, data):
|
||||
"""Create a test tag."""
|
||||
return self.postgres.insert("routine_tags", data)
|
||||
|
||||
def create_template(self, data):
|
||||
"""Create a test template."""
|
||||
return self.postgres.insert("routine_templates", data)
|
||||
|
||||
def create_template_step(self, data):
|
||||
"""Create a test template step."""
|
||||
return self.postgres.insert("routine_template_steps", data)
|
||||
|
||||
def create_streak(self, data):
|
||||
"""Create a test streak."""
|
||||
return self.postgres.insert("routine_streaks", data)
|
||||
|
||||
def cleanup(self, user_uuid):
|
||||
"""Clean up test data for a user."""
|
||||
# Delete in reverse order of dependencies
|
||||
self.postgres.delete("routine_streaks", {"user_uuid": user_uuid})
|
||||
self.postgres.delete("routine_session_notes", {})
|
||||
self.postgres.delete("routine_sessions", {"user_uuid": user_uuid})
|
||||
self.postgres.delete("routine_steps", {})
|
||||
self.postgres.delete("routine_routine_tags", {})
|
||||
self.postgres.delete("routine_schedules", {})
|
||||
self.postgres.delete("routine_template_steps", {})
|
||||
self.postgres.delete("routine_templates", {})
|
||||
self.postgres.delete("routines", {"user_uuid": user_uuid})
|
||||
self.postgres.delete("users", {"id": user_uuid})
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def db_helper():
|
||||
"""Fixture that provides a DBHelper instance."""
|
||||
return DBHelper()
|
||||
2
tests/integration/__init__.py
Normal file
2
tests/integration/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# tests/integration/__init__.py
|
||||
# Integration tests package
|
||||
286
tests/test_routines_api.py
Normal file
286
tests/test_routines_api.py
Normal file
@@ -0,0 +1,286 @@
|
||||
"""
|
||||
Comprehensive test script for Extended Routines API
|
||||
|
||||
This script can be run manually to test all endpoints.
|
||||
Usage: python test_routines_api.py
|
||||
"""
|
||||
|
||||
import requests
|
||||
import json
|
||||
import sys
|
||||
import uuid
|
||||
import time
|
||||
|
||||
BASE_URL = "http://localhost:8080"
|
||||
|
||||
# Test user credentials
|
||||
TEST_USERNAME = "testuser"
|
||||
TEST_PASSWORD = "testpass123"
|
||||
|
||||
def get_token():
|
||||
"""Login and get auth token."""
|
||||
resp = requests.post(f"{BASE_URL}/api/login", json={
|
||||
"username": TEST_USERNAME,
|
||||
"password": TEST_PASSWORD
|
||||
})
|
||||
if resp.status_code == 200:
|
||||
return resp.json()["token"]
|
||||
print(f"Login failed: {resp.text}")
|
||||
return None
|
||||
|
||||
def make_request(method, endpoint, token, data=None):
|
||||
"""Make authenticated API request."""
|
||||
headers = {
|
||||
"Authorization": f"Bearer {token}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
url = f"{BASE_URL}{endpoint}"
|
||||
resp = requests.request(method, url, headers=headers, json=data)
|
||||
return resp
|
||||
|
||||
def test_medications_crud(token):
|
||||
"""Test medications CRUD operations."""
|
||||
print("\n=== Testing Medications CRUD ===")
|
||||
|
||||
# List medications
|
||||
resp = make_request("GET", "/api/medications", token)
|
||||
print(f"GET /api/medications: {resp.status_code}")
|
||||
|
||||
# Add medication
|
||||
med_data = {
|
||||
"name": f"Test Med {uuid.uuid4().hex[:6]}",
|
||||
"dosage": "100",
|
||||
"unit": "mg",
|
||||
"frequency": "daily",
|
||||
"times": ["08:00"]
|
||||
}
|
||||
resp = make_request("POST", "/api/medications", token, med_data)
|
||||
print(f"POST /api/medications: {resp.status_code}")
|
||||
med_id = resp.json().get("id")
|
||||
|
||||
# Get medication
|
||||
if med_id:
|
||||
resp = make_request("GET", f"/api/medications/{med_id}", token)
|
||||
print(f"GET /api/medications/{med_id}: {resp.status_code}")
|
||||
|
||||
# Update medication
|
||||
resp = make_request("PUT", f"/api/medications/{med_id}", token, {"notes": "test note"})
|
||||
print(f"PUT /api/medications/{med_id}: {resp.status_code}")
|
||||
|
||||
# Take medication
|
||||
resp = make_request("POST", f"/api/medications/{med_id}/take", token, {"scheduled_time": "08:00"})
|
||||
print(f"POST /api/medications/{med_id}/take: {resp.status_code}")
|
||||
|
||||
# Get adherence
|
||||
resp = make_request("GET", f"/api/medications/{med_id}/adherence", token)
|
||||
print(f"GET /api/medications/{med_id}/adherence: {resp.status_code}")
|
||||
|
||||
# Delete medication
|
||||
resp = make_request("DELETE", f"/api/medications/{med_id}", token)
|
||||
print(f"DELETE /api/medications/{med_id}: {resp.status_code}")
|
||||
|
||||
def test_routines_crud(token):
|
||||
"""Test routines CRUD operations."""
|
||||
print("\n=== Testing Routines CRUD ===")
|
||||
|
||||
# List routines
|
||||
resp = make_request("GET", "/api/routines", token)
|
||||
print(f"GET /api/routines: {resp.status_code}")
|
||||
|
||||
# Create routine
|
||||
routine_data = {
|
||||
"name": f"Test Routine {uuid.uuid4().hex[:6]}",
|
||||
"description": "A test routine"
|
||||
}
|
||||
resp = make_request("POST", "/api/routines", token, routine_data)
|
||||
print(f"POST /api/routines: {resp.status_code}")
|
||||
routine_id = resp.json().get("id")
|
||||
|
||||
if routine_id:
|
||||
# Get routine
|
||||
resp = make_request("GET", f"/api/routines/{routine_id}", token)
|
||||
print(f"GET /api/routines/{routine_id}: {resp.status_code}")
|
||||
|
||||
# Add step
|
||||
step_data = {
|
||||
"name": "Test Step",
|
||||
"duration_minutes": 5
|
||||
}
|
||||
resp = make_request("POST", f"/api/routines/{routine_id}/steps", token, step_data)
|
||||
print(f"POST /api/routines/{routine_id}/steps: {resp.status_code}")
|
||||
step_id = resp.json().get("id")
|
||||
|
||||
if step_id:
|
||||
# Update step instructions
|
||||
resp = make_request("PUT", f"/api/routines/{routine_id}/steps/{step_id}/instructions",
|
||||
token, {"instructions": "Do this step carefully"})
|
||||
print(f"PUT /steps/{step_id}/instructions: {resp.status_code}")
|
||||
|
||||
# Update step type
|
||||
resp = make_request("PUT", f"/api/routines/{routine_id}/steps/{step_id}/type",
|
||||
token, {"step_type": "timer"})
|
||||
print(f"PUT /steps/{step_id}/type: {resp.status_code}")
|
||||
|
||||
# Update step media
|
||||
resp = make_request("PUT", f"/api/routines/{routine_id}/steps/{step_id}/media",
|
||||
token, {"media_url": "https://example.com/audio.mp3"})
|
||||
print(f"PUT /steps/{step_id}/media: {resp.status_code}")
|
||||
|
||||
# Start session
|
||||
resp = make_request("POST", f"/api/routines/{routine_id}/start", token)
|
||||
print(f"POST /routines/{routine_id}/start: {resp.status_code}")
|
||||
session_id = resp.json().get("session", {}).get("id")
|
||||
|
||||
if session_id:
|
||||
# Complete step
|
||||
resp = make_request("POST", f"/api/sessions/{session_id}/complete-step", token)
|
||||
print(f"POST /sessions/{session_id}/complete-step: {resp.status_code}")
|
||||
|
||||
# Pause session (if still active)
|
||||
resp = make_request("POST", f"/api/routines/{routine_id}/start", token)
|
||||
if resp.status_code == 201:
|
||||
session_id2 = resp.json().get("session", {}).get("id")
|
||||
resp = make_request("POST", f"/api/sessions/{session_id2}/pause", token)
|
||||
print(f"POST /sessions/{session_id2}/pause: {resp.status_code}")
|
||||
|
||||
# Resume session
|
||||
resp = make_request("POST", f"/api/sessions/{session_id2}/resume", token)
|
||||
print(f"POST /sessions/{session_id2}/resume: {resp.status_code}")
|
||||
|
||||
# Abort session
|
||||
resp = make_request("POST", f"/api/sessions/{session_id2}/abort", token, {"reason": "Test abort"})
|
||||
print(f"POST /sessions/{session_id2}/abort: {resp.status_code}")
|
||||
|
||||
# Get session details
|
||||
resp = make_request("GET", f"/api/sessions/{session_id}", token)
|
||||
print(f"GET /sessions/{session_id}: {resp.status_code}")
|
||||
|
||||
# Get stats
|
||||
resp = make_request("GET", f"/api/routines/{routine_id}/stats", token)
|
||||
print(f"GET /routines/{routine_id}/stats: {resp.status_code}")
|
||||
|
||||
# Get streak
|
||||
resp = make_request("GET", f"/api/routines/{routine_id}/streak", token)
|
||||
print(f"GET /routines/{routine_id}/streak: {resp.status_code}")
|
||||
|
||||
# Delete routine
|
||||
resp = make_request("DELETE", f"/api/routines/{routine_id}", token)
|
||||
print(f"DELETE /api/routines/{routine_id}: {resp.status_code}")
|
||||
|
||||
def test_templates(token):
|
||||
"""Test template operations."""
|
||||
print("\n=== Testing Templates ===")
|
||||
|
||||
# List templates
|
||||
resp = make_request("GET", "/api/templates", token)
|
||||
print(f"GET /api/templates: {resp.status_code}")
|
||||
|
||||
# Create template
|
||||
template_data = {
|
||||
"name": f"Test Template {uuid.uuid4().hex[:6]}",
|
||||
"description": "A test template"
|
||||
}
|
||||
resp = make_request("POST", "/api/templates", token, template_data)
|
||||
print(f"POST /api/templates: {resp.status_code}")
|
||||
template_id = resp.json().get("id")
|
||||
|
||||
if template_id:
|
||||
# Get template
|
||||
resp = make_request("GET", f"/api/templates/{template_id}", token)
|
||||
print(f"GET /api/templates/{template_id}: {resp.status_code}")
|
||||
|
||||
# Add template step
|
||||
step_data = {"name": "Template Step 1"}
|
||||
resp = make_request("POST", f"/api/templates/{template_id}/steps", token, step_data)
|
||||
print(f"POST /templates/{template_id}/steps: {resp.status_code}")
|
||||
|
||||
# Clone template
|
||||
resp = make_request("POST", f"/api/templates/{template_id}/clone", token)
|
||||
print(f"POST /templates/{template_id}/clone: {resp.status_code}")
|
||||
|
||||
# Delete template
|
||||
resp = make_request("DELETE", f"/api/templates/{template_id}", token)
|
||||
print(f"DELETE /api/templates/{template_id}: {resp.status_code}")
|
||||
|
||||
def test_tags(token):
|
||||
"""Test tag operations."""
|
||||
print("\n=== Testing Tags ===")
|
||||
|
||||
# List tags
|
||||
resp = make_request("GET", "/api/tags", token)
|
||||
print(f"GET /api/tags: {resp.status_code}")
|
||||
|
||||
# Create tag
|
||||
tag_data = {
|
||||
"name": f"testtag_{uuid.uuid4().hex[:6]}",
|
||||
"color": "#FF0000"
|
||||
}
|
||||
resp = make_request("POST", "/api/tags", token, tag_data)
|
||||
print(f"POST /api/tags: {resp.status_code}")
|
||||
tag_id = resp.json().get("id")
|
||||
|
||||
# Get streaks
|
||||
resp = make_request("GET", "/api/routines/streaks", token)
|
||||
print(f"GET /api/routines/streaks: {resp.status_code}")
|
||||
|
||||
# Get weekly summary
|
||||
resp = make_request("GET", "/api/routines/weekly-summary", token)
|
||||
print(f"GET /api/routines/weekly-summary: {resp.status_code}")
|
||||
|
||||
if tag_id:
|
||||
# Delete tag
|
||||
resp = make_request("DELETE", f"/api/tags/{tag_id}", token)
|
||||
print(f"DELETE /api/tags/{tag_id}: {resp.status_code}")
|
||||
|
||||
def test_auth_errors(token):
|
||||
"""Test authentication errors."""
|
||||
print("\n=== Testing Auth Errors ===")
|
||||
|
||||
# Request without token
|
||||
resp = requests.get(f"{BASE_URL}/api/medications")
|
||||
print(f"GET /api/medications (no token): {resp.status_code}")
|
||||
|
||||
# Request with invalid token
|
||||
resp = requests.get(f"{BASE_URL}/api/medications",
|
||||
headers={"Authorization": "Bearer invalid_token"})
|
||||
print(f"GET /api/medications (invalid token): {resp.status_code}")
|
||||
|
||||
def main():
|
||||
"""Run all tests."""
|
||||
print("=" * 50)
|
||||
print("Extended Routines API - Comprehensive Test")
|
||||
print("=" * 50)
|
||||
|
||||
# Wait for API to be ready
|
||||
print("\nWaiting for API...")
|
||||
for i in range(10):
|
||||
try:
|
||||
resp = requests.get(f"{BASE_URL}/health")
|
||||
if resp.status_code == 200:
|
||||
print("API is ready!")
|
||||
break
|
||||
except:
|
||||
pass
|
||||
time.sleep(1)
|
||||
|
||||
# Get auth token
|
||||
token = get_token()
|
||||
if not token:
|
||||
print("Failed to get auth token")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"Got auth token: {token[:20]}...")
|
||||
|
||||
# Run tests
|
||||
test_auth_errors(token)
|
||||
test_medications_crud(token)
|
||||
test_routines_crud(token)
|
||||
test_templates(token)
|
||||
test_tags(token)
|
||||
|
||||
print("\n" + "=" * 50)
|
||||
print("All tests completed!")
|
||||
print("=" * 50)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user