""" Unit tests for recipe models and validation. """ import pytest from datetime import datetime from src.tempering_machine.shared.models.recipe import Recipe, RecipePhase class TestRecipe: """Test cases for Recipe model.""" def test_recipe_creation(self): """Test basic recipe creation.""" recipe = Recipe( name="Test Recipe", heating_goal=46.0, cooling_goal=27.0, tank_temp=45.0, fountain_temp=32.0 ) assert recipe.name == "Test Recipe" assert recipe.heating_goal == 46.0 assert recipe.cooling_goal == 27.0 assert recipe.is_active is True assert recipe.version == 1 def test_recipe_temperature_validation_valid(self): """Test valid temperature parameters.""" recipe = Recipe( name="Valid Recipe", heating_goal=50.0, cooling_goal=25.0, pouring_goal=30.0, tank_temp=45.0, fountain_temp=32.0 ) assert recipe.validate_temperatures() is True def test_recipe_temperature_validation_invalid_cooling_too_high(self): """Test invalid temperature parameters - cooling goal too high.""" recipe = Recipe( name="Invalid Recipe", heating_goal=45.0, cooling_goal=50.0, # Higher than heating goal tank_temp=45.0, fountain_temp=32.0 ) assert recipe.validate_temperatures() is False def test_recipe_temperature_validation_invalid_ranges(self): """Test invalid temperature ranges.""" # Heating goal too low recipe1 = Recipe( name="Invalid Recipe 1", heating_goal=35.0, # Below minimum of 40°C cooling_goal=25.0, tank_temp=45.0, fountain_temp=32.0 ) assert recipe1.validate_temperatures() is False # Cooling goal too high recipe2 = Recipe( name="Invalid Recipe 2", heating_goal=50.0, cooling_goal=45.0, # Above maximum of 40°C tank_temp=45.0, fountain_temp=32.0 ) assert recipe2.validate_temperatures() is False def test_recipe_pouring_goal_validation(self): """Test pouring goal validation.""" # Valid pouring goal within range recipe1 = Recipe( name="Valid Pouring", heating_goal=50.0, cooling_goal=25.0, pouring_goal=30.0, # Between cooling and heating tank_temp=45.0, fountain_temp=32.0 ) assert recipe1.validate_temperatures() is True # Invalid pouring goal - too low recipe2 = Recipe( name="Invalid Pouring Low", heating_goal=50.0, cooling_goal=25.0, pouring_goal=20.0, # Below cooling goal tank_temp=45.0, fountain_temp=32.0 ) assert recipe2.validate_temperatures() is False # Invalid pouring goal - too high recipe3 = Recipe( name="Invalid Pouring High", heating_goal=50.0, cooling_goal=25.0, pouring_goal=55.0, # Above heating goal tank_temp=45.0, fountain_temp=32.0 ) assert recipe3.validate_temperatures() is False def test_get_phase_sequence(self): """Test phase sequence generation.""" recipe = Recipe( name="Phase Test", heating_goal=46.0, cooling_goal=27.0, tank_temp=45.0, fountain_temp=32.0 ) phases = recipe.get_phase_sequence() expected_phases = [ RecipePhase.PREHEATING, RecipePhase.HEATING, RecipePhase.HEATING_DELAY, RecipePhase.COOLING, RecipePhase.COOLING_DELAY, RecipePhase.POURING ] assert phases == expected_phases def test_recipe_to_dict(self): """Test recipe serialization to dictionary.""" recipe = Recipe( name="Serialization Test", description="Test description", heating_goal=46.0, cooling_goal=27.0, pouring_goal=30.0, tank_temp=45.0, fountain_temp=32.0, mixer_enabled=True, fountain_enabled=True, pedal_on_time=2.5, pedal_off_time=3.5 ) recipe_dict = recipe.to_dict() assert recipe_dict["name"] == "Serialization Test" assert recipe_dict["description"] == "Test description" assert recipe_dict["heating_goal"] == 46.0 assert recipe_dict["cooling_goal"] == 27.0 assert recipe_dict["pouring_goal"] == 30.0 assert recipe_dict["mixer_enabled"] is True assert recipe_dict["pedal_on_time"] == 2.5 assert recipe_dict["pedal_off_time"] == 3.5 assert recipe_dict["version"] == 1 assert recipe_dict["is_active"] is True def test_from_csv_row(self): """Test creating recipe from CSV data.""" csv_row = { "ID": "1", "Name": "CSV Recipe", "HeatingGoal": "46.0", "CoolingGoal": "27.0", "PouringGoal": "30.0", "TankTemp": "45.0", "FountainTemp": "32.0", "Mixer": "1", "Fountain": "1", "MoldHeater": "0", "Vibration": "0", "VibHeater": "0", "Pedal": "1", "PedalOnTime": "2.0", "PedalOffTime": "3.0" } recipe = Recipe.from_csv_row(csv_row) assert recipe.id == 1 assert recipe.name == "CSV Recipe" assert recipe.heating_goal == 46.0 assert recipe.cooling_goal == 27.0 assert recipe.pouring_goal == 30.0 assert recipe.mixer_enabled is True assert recipe.mold_heater_enabled is False assert recipe.pedal_on_time == 2.0 class TestRecipePhase: """Test cases for RecipePhase enum.""" def test_recipe_phase_values(self): """Test recipe phase enum values.""" assert RecipePhase.PREHEATING.value == "preheating" assert RecipePhase.HEATING.value == "heating" assert RecipePhase.HEATING_DELAY.value == "heating_delay" assert RecipePhase.COOLING.value == "cooling" assert RecipePhase.COOLING_DELAY.value == "cooling_delay" assert RecipePhase.POURING.value == "pouring" assert RecipePhase.COMPLETED.value == "completed" assert RecipePhase.STOPPED.value == "stopped" assert RecipePhase.ERROR.value == "error" def test_recipe_phase_membership(self): """Test recipe phase enum membership.""" assert RecipePhase.PREHEATING in RecipePhase assert RecipePhase.HEATING in RecipePhase assert RecipePhase.COMPLETED in RecipePhase # Test string conversion assert str(RecipePhase.HEATING) == "RecipePhase.HEATING"