test_parsing.py (4563B)
1 from fractions import Fraction 2 3 from parsing import ( 4 Item, 5 group_by_category, 6 merge_ingredients, 7 parse_quantity, 8 parse_recipe_text, 9 suggest_keto, 10 ) 11 12 13 def test_parse_quantity_whole_number(): 14 assert parse_quantity("2") == Fraction(2) 15 16 17 def test_parse_quantity_fraction(): 18 assert parse_quantity("1/2") == Fraction(1, 2) 19 20 21 def test_parse_quantity_mixed_number(): 22 assert parse_quantity("1 1/2") == Fraction(3, 2) 23 24 25 def test_parse_quantity_unparseable_returns_none(): 26 assert parse_quantity("a pinch") is None 27 28 29 def test_merge_sums_matching_name_and_unit(): 30 items = [ 31 Item(name="Milk", quantity="1", unit="cup", category="dairy", source="staple"), 32 Item(name="milk", quantity="1", unit="cup", category="dairy", source="recipe"), 33 ] 34 merged = merge_ingredients(items) 35 assert len(merged) == 1 36 assert merged[0].quantity == "2" 37 38 39 def test_merge_keeps_mismatched_units_separate(): 40 items = [ 41 Item(name="Flour", quantity="1", unit="cup", category="pantry", source="staple"), 42 Item(name="Flour", quantity="200", unit="g", category="pantry", source="recipe"), 43 ] 44 merged = merge_ingredients(items) 45 assert len(merged) == 2 46 47 48 def test_merge_keeps_unparseable_quantities_separate(): 49 items = [ 50 Item(name="Salt", quantity="a pinch", unit=None, category="pantry", source="recipe"), 51 Item(name="Salt", quantity="a pinch", unit=None, category="pantry", source="recipe"), 52 ] 53 merged = merge_ingredients(items) 54 assert len(merged) == 2 55 56 57 def test_parse_recipe_text_basic(): 58 body = ( 59 "Servings: 4\n" 60 "Source: test\n" 61 "Keto: yes\n" 62 "Ingredients:\n" 63 "1 | lb | ground beef | meat\n" 64 "1 | cup | diced tomatoes | pantry\n" 65 "Instructions:\n" 66 "Brown the beef.\n" 67 "Simmer.\n" 68 ) 69 parsed = parse_recipe_text("Test Chili", body) 70 assert parsed["name"] == "Test Chili" 71 assert parsed["servings"] == 4 72 assert parsed["is_keto"] is True 73 assert len(parsed["ingredients"]) == 2 74 assert "Brown the beef." in parsed["instructions"] 75 76 77 def test_parse_recipe_text_missing_name_raises(): 78 try: 79 parse_recipe_text(" ", "Instructions:\nDo stuff.\n") 80 assert False, "expected ValueError" 81 except ValueError: 82 pass 83 84 85 def test_parse_recipe_text_freeform_real_world_paste(): 86 # Shape of a recipe copy-pasted straight from a blog: no header before 87 # ingredients, freeform ingredient lines (no "|"), a bare "INSTRUCTIONS" 88 # header with no colon, and a trailing "NUTRITION" section to discard. 89 body = ( 90 "2 tablespoons pork lard, or butter\n" 91 "3 pounds chicken pieces, bone-in and skin-on\n" 92 "2 medium yellow onions, very finely chopped\n" 93 "\n" 94 "INSTRUCTIONS\n" 95 "\n" 96 "Heat the lard in a large Dutch oven and brown the chicken.\n" 97 "Add the onions and fry until golden brown.\n" 98 "\n" 99 "NUTRITION\n" 100 "Calories: 500\n" 101 ) 102 parsed = parse_recipe_text("Chicken Paprikash", body) 103 assert parsed["name"] == "Chicken Paprikash" 104 assert len(parsed["ingredients"]) == 3 105 assert parsed["ingredients"][0]["name"] == "2 tablespoons pork lard, or butter" 106 assert parsed["ingredients"][0]["quantity"] is None 107 assert "brown the chicken" in parsed["instructions"] 108 assert "Calories" not in parsed["instructions"] 109 110 111 def test_suggest_keto_flags_high_carb_ingredient(): 112 assert suggest_keto(["ground beef", "flour"]) is False 113 114 115 def test_suggest_keto_true_when_no_high_carb_keywords(): 116 assert suggest_keto(["ground beef", "cheese"]) is True 117 118 119 def test_group_by_category_groups_and_puts_uncategorized_last(): 120 items = [ 121 Item(name="Milk", quantity="1", unit="cup", category="dairy", source="staple"), 122 Item(name="Onion", quantity="1", unit=None, category=None, source="recipe"), 123 Item(name="Cheese", quantity="1", unit="cup", category="dairy", source="staple"), 124 Item(name="Flour", quantity="1", unit="cup", category="pantry", source="staple"), 125 ] 126 grouped = group_by_category(items) 127 categories = [cat for cat, _ in grouped] 128 assert categories == ["dairy", "pantry", None] 129 assert [i.name for i in dict(grouped)["dairy"]] == ["Milk", "Cheese"] 130 131 132 def test_group_by_category_no_uncategorized_bucket_when_none_missing(): 133 items = [ 134 Item(name="Milk", quantity="1", unit="cup", category="dairy", source="staple"), 135 ] 136 grouped = group_by_category(items) 137 assert grouped == [("dairy", items)]