from decimal import Decimal import pytest from recipes.parsing import ( format_amount, ingredients_to_text, parse_ingredient_line, parse_ingredients, parse_steps, parse_tags, scale_amount, ) @pytest.mark.parametrize( "line, amount, amount_max, unit, name, note", [ ("200 g Mehl, gesiebt", "200", None, "g", "Mehl", "gesiebt"), ("200g Mehl", "200", None, "g", "Mehl", ""), ("1,5l Milch", "1.5", None, "l", "Milch", ""), ("1 ½ TL Salz", "1.5", None, "TL", "Salz", ""), ("1/2 Bund Petersilie", "0.5", None, "Bund", "Petersilie", ""), ("2 1/2 Tassen Reis", "2.5", None, "Tassen", "Reis", ""), ("2-3 Zehen Knoblauch", "2", "3", "Zehen", "Knoblauch", ""), ("2 bis 3 EL Öl", "2", "3", "EL", "Öl", ""), ("2 Eier", "2", None, "", "Eier", ""), ("3 Essl. Zucker", "3", None, "EL", "Zucker", ""), ("- 1 Prise Salz", "1", None, "Prise", "Salz", ""), ("½ Zitrone, nur Saft", "0.5", None, "", "Zitrone", "nur Saft"), ("Salz und Pfeffer", None, None, "", "Salz und Pfeffer", ""), ("1 Dose Tomaten (400 g)", "1", None, "Dose", "Tomaten (400 g)", ""), ], ) def test_parse_ingredient_line(line, amount, amount_max, unit, name, note): item = parse_ingredient_line(line) assert item.amount == (Decimal(amount) if amount else None) assert item.amount_max == (Decimal(amount_max) if amount_max else None) assert (item.unit, item.name, item.note) == (unit, name, note) def test_parse_ingredients_with_groups(): items = parse_ingredients("Für den Teig:\n200 g Mehl\n\nFür die Soße:\n1 Dose Tomaten\n") assert [(i.group, i.name) for i in items] == [("Für den Teig", "Mehl"), ("Für die Soße", "Tomaten")] def test_ingredient_text_roundtrip(): text = "200 g Mehl, gesiebt\n2-3 Zehen Knoblauch\n\nFür die Soße:\n½ TL Salz\nPfeffer" items = parse_ingredients(text) assert parse_ingredients(ingredients_to_text(items)) == items def test_parse_steps_by_blank_lines(): assert parse_steps("Ofen vorheizen.\nAuf 180 °C.\n\n2. Mischen.") == ["Ofen vorheizen. Auf 180 °C.", "Mischen."] def test_parse_steps_by_lines_and_strip_numbers(): assert parse_steps("1. Schneiden\n2) Braten\nSchritt 3: Servieren") == ["Schneiden", "Braten", "Servieren"] def test_parse_tags_lowercase_unique(): assert parse_tags("Pasta, #Vegetarisch, Schnell Gemacht ,pasta,") == ["pasta", "vegetarisch", "schnell gemacht"] @pytest.mark.parametrize( "value, expected", [("2", "2"), ("0.5", "½"), ("1.5", "1 ½"), ("0.333", "⅓"), ("0.25", "¼"), ("2.37", "2,37"), ("1.999", "2")], ) def test_format_amount(value, expected): assert format_amount(Decimal(value)) == expected def test_scale_amount_normalises_metric(): assert scale_amount(Decimal(600), None, "g", Decimal(2)) == (Decimal("1.2"), None, "kg") assert scale_amount(Decimal(250), None, "ml", Decimal("0.5")) == (Decimal(125), None, "ml") assert scale_amount(Decimal(2), Decimal(3), "EL", Decimal(2)) == (Decimal(4), Decimal(6), "EL") assert scale_amount(None, None, "", Decimal(2)) == (None, None, "")