""" Integration tests for Phase 1 Daily Helper API endpoints """ import pytest import json from datetime import date, datetime from fastapi.testclient import TestClient class TestUserProfileAPI: """Tests for User Profile API endpoints""" def test_create_user_profile(self, client): """Test creating a user profile""" payload = { "email": "test@example.com", "username": "testuser", "timezone": "EST", "trading_style": "day_trader", "risk_tolerance": "moderate", "preferred_trading_start": "09:00", "preferred_trading_end": "17:00", "daily_target": 1000.0, "max_loss": 500.0, } response = client.post("/api/daily-helper/profile", json=payload) assert response.status_code == 201 data = response.json() assert data["email"] == "test@example.com" assert data["timezone"] == "EST" def test_get_user_profile(self, client, user_profile): """Test retrieving user profile""" response = client.get("/api/daily-helper/profile") assert response.status_code == 200 data = response.json() assert "id" in data assert "email" in data def test_update_user_profile(self, client, user_profile): """Test updating user profile""" payload = { "timezone": "PST", "daily_target": 2000.0, } response = client.put("/api/daily-helper/profile", json=payload) assert response.status_code == 200 data = response.json() assert data["timezone"] == "PST" assert data["daily_target"] == 2000.0 def test_profile_validation(self, client): """Test profile input validation""" # Missing required fields payload = { "email": "test@example.com", } response = client.post("/api/daily-helper/profile", json=payload) # Should still succeed with defaults assert response.status_code in [200, 201] class TestDailyRoutineAPI: """Tests for Daily Routine API endpoints""" def test_create_routine(self, client): """Test creating a daily routine""" payload = { "routine_type": "morning", "scheduled_time": "08:30", "tasks": ["market_brief", "checklist", "review_plan"], "enabled": True, } response = client.post("/api/daily-helper/routines", json=payload) assert response.status_code == 201 data = response.json() assert data["routine_type"] == "morning" assert len(data["tasks"]) == 3 def test_list_routines(self, client, daily_routine): """Test listing routines""" response = client.get("/api/daily-helper/routines") assert response.status_code == 200 data = response.json() assert isinstance(data, list) assert len(data) > 0 def test_get_routine(self, client, daily_routine): """Test retrieving a specific routine""" response = client.get(f"/api/daily-helper/routines/{daily_routine.id}") assert response.status_code == 200 data = response.json() assert data["id"] == daily_routine.id def test_update_routine(self, client, daily_routine): """Test updating a routine""" payload = { "scheduled_time": "09:00", "enabled": False, } response = client.put( f"/api/daily-helper/routines/{daily_routine.id}", json=payload ) assert response.status_code == 200 data = response.json() assert data["scheduled_time"] == "09:00" assert data["enabled"] == False def test_filter_routines(self, client, daily_routine): """Test filtering routines""" response = client.get( f"/api/daily-helper/routines?routine_type=morning" ) assert response.status_code == 200 data = response.json() for routine in data: assert routine["routine_type"] == "morning" def test_execute_routine(self, client, daily_routine): """Test executing a routine""" response = client.post( f"/api/daily-helper/routines/{daily_routine.id}/execute" ) assert response.status_code == 201 data = response.json() assert "completion_status" in data def test_get_routine_executions(self, client, daily_routine): """Test retrieving routine execution history""" response = client.get( f"/api/daily-helper/routines/{daily_routine.id}/executions" ) assert response.status_code == 200 data = response.json() assert isinstance(data, list) class TestNotificationAPI: """Tests for Notification API endpoints""" def test_create_notification(self, client): """Test creating a notification""" payload = { "notification_type": "price_alert", "title": "Price Alert", "message": "Gold price exceeded $2000", "priority": "high", "delivery_method": "push", } response = client.post("/api/daily-helper/notifications", json=payload) assert response.status_code == 201 data = response.json() assert data["notification_type"] == "price_alert" assert data["read"] == False def test_list_notifications(self, client, notification): """Test listing notifications""" response = client.get("/api/daily-helper/notifications") assert response.status_code == 200 data = response.json() assert "notifications" in data assert "unread_count" in data assert "total_count" in data def test_get_notification(self, client, notification): """Test retrieving a specific notification""" response = client.get(f"/api/daily-helper/notifications/{notification.id}") assert response.status_code == 200 data = response.json() assert data["id"] == notification.id def test_mark_notification_read(self, client, notification): """Test marking notification as read""" response = client.put( f"/api/daily-helper/notifications/{notification.id}/read" ) assert response.status_code == 200 data = response.json() assert data["read"] == True def test_mark_all_notifications_read(self, client, notification): """Test marking all notifications as read""" response = client.post( "/api/daily-helper/notifications/mark-all-read" ) assert response.status_code == 200 def test_filter_notifications(self, client, notification): """Test filtering notifications""" response = client.get( "/api/daily-helper/notifications?notification_type=price_alert" ) assert response.status_code == 200 data = response.json() for notif in data["notifications"]: assert notif["notification_type"] == "price_alert" class TestDailyChecklistAPI: """Tests for Daily Checklist API endpoints""" def test_create_checklist(self, client): """Test creating a daily checklist""" payload = { "checklist_type": "morning", "items": [ {"id": "1", "title": "Check Economic Calendar", "completed": False}, {"id": "2", "title": "Create Trading Plan", "completed": False}, ], "notes": "Daily morning checklist", } response = client.post("/api/daily-helper/checklists", json=payload) assert response.status_code == 201 data = response.json() assert data["checklist_type"] == "morning" assert len(data["items"]) == 2 def test_get_today_checklist(self, client, daily_checklist): """Test retrieving today's checklist""" response = client.get("/api/daily-helper/checklists/today") assert response.status_code == 200 data = response.json() if data: # Might be None if none exists assert data["checklist_date"] == date.today().isoformat() def test_list_checklists(self, client, daily_checklist): """Test listing checklists""" response = client.get("/api/daily-helper/checklists") assert response.status_code == 200 data = response.json() assert isinstance(data, list) def test_update_checklist(self, client, daily_checklist): """Test updating a checklist""" payload = { "notes": "Updated notes", } response = client.put( f"/api/daily-helper/checklists/{daily_checklist.id}", json=payload ) assert response.status_code == 200 data = response.json() assert data["notes"] == "Updated notes" def test_update_checklist_item(self, client, daily_checklist): """Test updating a specific checklist item""" # Assume first item exists item_id = daily_checklist.items[0]["id"] if daily_checklist.items else "1" response = client.put( f"/api/daily-helper/checklists/{daily_checklist.id}/items/{item_id}", json={"completed": True} ) assert response.status_code == 200 data = response.json() # Should have updated completion percentage assert data["completion_percentage"] >= 0 class TestHabitTrackerAPI: """Tests for Habit Tracker API endpoints""" def test_create_habit(self, client): """Test creating a habit""" payload = { "habit_name": "Daily Planning", "frequency": "daily", } response = client.post("/api/daily-helper/habits", json=payload) assert response.status_code == 201 data = response.json() assert data["habit_name"] == "Daily Planning" assert data["current_streak"] == 0 def test_list_habits(self, client, habit): """Test listing habits""" response = client.get("/api/daily-helper/habits") assert response.status_code == 200 data = response.json() assert isinstance(data, list) def test_get_habit(self, client, habit): """Test retrieving a specific habit""" response = client.get(f"/api/daily-helper/habits/{habit.id}") assert response.status_code == 200 data = response.json() assert data["id"] == habit.id def test_log_habit_completion(self, client, habit): """Test logging habit completion""" payload = { "habit_id": habit.id, } response = client.post( f"/api/daily-helper/habits/{habit.id}/log", json=payload ) assert response.status_code == 200 data = response.json() assert data["total_completions"] >= 1 def test_habit_streak_update(self, client, habit): """Test that habit streak updates on completion""" # Log completion payload = {"habit_id": habit.id} response = client.post( f"/api/daily-helper/habits/{habit.id}/log", json=payload ) assert response.status_code == 200 data = response.json() assert data["current_streak"] >= 0 class TestDashboardAPI: """Tests for Dashboard summary endpoint""" def test_get_dashboard_summary(self, client): """Test getting dashboard summary""" response = client.get("/api/daily-helper/dashboard") assert response.status_code == 200 data = response.json() assert "today_date" in data assert "checklists" in data assert "unread_notifications" in data assert "habits_summary" in data assert "pending_routines" in data class TestErrorHandling: """Tests for error handling""" def test_not_found_error(self, client): """Test 404 error handling""" response = client.get("/api/daily-helper/routines/99999") assert response.status_code == 404 def test_invalid_data_error(self, client): """Test validation error handling""" payload = { "routine_type": "morning", # Missing required field: scheduled_time } response = client.post("/api/daily-helper/routines", json=payload) # Should fail validation assert response.status_code in [400, 422] # Fixtures @pytest.fixture def client(): """Create test client""" from fastapi.testclient import TestClient from app.main import app return TestClient(app) @pytest.fixture def user_profile(client, db): """Create a test user profile""" payload = { "email": "test@example.com", "timezone": "EST", } response = client.post("/api/daily-helper/profile", json=payload) return response.json() @pytest.fixture def daily_routine(client): """Create a test daily routine""" payload = { "routine_type": "morning", "scheduled_time": "08:30", "tasks": ["market_brief"], "enabled": True, } response = client.post("/api/daily-helper/routines", json=payload) return response.json() @pytest.fixture def notification(client): """Create a test notification""" payload = { "notification_type": "price_alert", "title": "Test Alert", "message": "Test message", } response = client.post("/api/daily-helper/notifications", json=payload) return response.json() @pytest.fixture def daily_checklist(client): """Create a test daily checklist""" payload = { "checklist_type": "morning", "items": [ {"id": "1", "title": "Item 1", "completed": False}, ], } response = client.post("/api/daily-helper/checklists", json=payload) return response.json() @pytest.fixture def habit(client): """Create a test habit""" payload = { "habit_name": "Test Habit", "frequency": "daily", } response = client.post("/api/daily-helper/habits", json=payload) return response.json() if __name__ == "__main__": pytest.main([__file__, "-v"])