#!/usr/bin/env python3 """ Unit tests for Habit Bot Tests: habit tracking, food logging, data persistence """ import pytest import sys import os import json from datetime import datetime, timedelta from unittest.mock import Mock, patch, MagicMock from io import StringIO # Add parent directory to path sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) # Test data directory TEST_DATA_DIR = '/tmp/test_habit_bot' os.makedirs(TEST_DATA_DIR, exist_ok=True) @pytest.fixture def mock_data(): """Create mock data for testing""" return { 'users': {}, 'habits': {}, 'habit_logs': {}, 'food_logs': {}, 'sessions': {} } class TestHabitBot: """Test habit tracking functionality""" def test_add_habit(self, mock_data): """Test adding a new habit""" habit_name = "morning workout" # Simulate adding habit user_id = "12345" if user_id not in mock_data['habits']: mock_data['habits'][user_id] = {} mock_data['habits'][user_id][habit_name] = { 'name': habit_name, 'streak': 0, 'created_at': datetime.now().isoformat(), 'is_active': True } assert user_id in mock_data['habits'] assert habit_name in mock_data['habits'][user_id] def test_habit_streak_increment(self, mock_data): """Test habit streak increment""" user_id = "12345" habit_name = "morning workout" # Initial streak mock_data['habits'][user_id] = { habit_name: { 'name': habit_name, 'streak': 0, 'last_completed': None } } # Increment streak mock_data['habits'][user_id][habit_name]['streak'] += 1 mock_data['habits'][user_id][habit_name]['last_completed'] = datetime.now().isoformat() assert mock_data['habits'][user_id][habit_name]['streak'] == 1 def test_habit_completion_reset(self, mock_data): """Test resetting habit streak when day changes""" user_id = "12345" habit_name = "morning workout" # Set streak mock_data['habits'][user_id] = { habit_name: { 'name': habit_name, 'streak': 5, 'last_completed': (datetime.now() - timedelta(days=2)).isoformat() } } # Check if streak should reset (more than 1 day since last completion) last_completed = datetime.fromisoformat(mock_data['habits'][user_id][habit_name]['last_completed']) days_since = (datetime.now() - last_completed).days if days_since > 1: mock_data['habits'][user_id][habit_name]['streak'] = 0 assert mock_data['habits'][user_id][habit_name]['streak'] == 0 def test_food_logging(self, mock_data): """Test food logging functionality""" user_id = "12345" food_entry = { 'food': "grilled chicken", 'calories': 300, 'protein': 50, 'carbs': 0, 'fat': 10, 'logged_at': datetime.now().isoformat() } if user_id not in mock_data['food_logs']: mock_data['food_logs'][user_id] = [] mock_data['food_logs'][user_id].append(food_entry) assert len(mock_data['food_logs'][user_id]) == 1 assert mock_data['food_logs'][user_id][0]['food'] == "grilled chicken" assert mock_data['food_logs'][user_id][0]['calories'] == 300 def test_daily_calorie_calculation(self, mock_data): """Test daily calorie calculation""" user_id = "12345" mock_data['food_logs'][user_id] = [ {'calories': 500, 'protein': 50, 'carbs': 20, 'fat': 15}, {'calories': 700, 'protein': 70, 'carbs': 30, 'fat': 20}, {'calories': 400, 'protein': 40, 'carbs': 10, 'fat': 12} ] total_calories = sum(entry['calories'] for entry in mock_data['food_logs'][user_id]) assert total_calories == 1600 def test_user_session_tracking(self, mock_data): """Test user session tracking""" user_id = "12345" session = { 'start_time': datetime.now().isoformat(), 'end_time': None, 'commands_executed': 0 } mock_data['sessions'][user_id] = session mock_data['sessions'][user_id]['commands_executed'] += 1 assert 'start_time' in mock_data['sessions'][user_id] assert mock_data['sessions'][user_id]['commands_executed'] == 1 def test_data_persistence(self, mock_data): """Test mock data persistence in fixture""" # Add multiple entries for i in range(5): habit_name = f"habit_{i}" mock_data['habits']['user1'][habit_name] = { 'name': habit_name, 'streak': i, 'created_at': datetime.now().isoformat() } assert len(mock_data['habits']['user1']) == 5