2022-01-13 13:06:52 -09:00
|
|
|
|
import shutil
|
2021-10-09 13:08:23 -08:00
|
|
|
|
from dataclasses import dataclass
|
|
|
|
|
from fractions import Fraction
|
|
|
|
|
|
|
|
|
|
import pytest
|
|
|
|
|
|
2021-10-16 16:06:13 -08:00
|
|
|
|
from mealie.services.parser_services import RegisteredParser, get_parser
|
2021-10-09 13:08:23 -08:00
|
|
|
|
from mealie.services.parser_services.crfpp.processor import CRFIngredient, convert_list_to_crf_model
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
|
class TestIngredient:
|
|
|
|
|
input: str
|
|
|
|
|
quantity: float
|
|
|
|
|
unit: str
|
|
|
|
|
food: str
|
|
|
|
|
comments: str
|
|
|
|
|
|
|
|
|
|
|
2021-10-16 16:06:13 -08:00
|
|
|
|
def crf_exists() -> bool:
|
|
|
|
|
return shutil.which("crf_test") is not None
|
|
|
|
|
|
|
|
|
|
|
2021-10-09 13:08:23 -08:00
|
|
|
|
# TODO - add more robust test cases
|
|
|
|
|
test_ingredients = [
|
|
|
|
|
TestIngredient("½ cup all-purpose flour", 0.5, "cup", "all-purpose flour", ""),
|
|
|
|
|
TestIngredient("1 ½ teaspoons ground black pepper", 1.5, "teaspoon", "black pepper", "ground"),
|
2022-06-10 21:18:31 -05:00
|
|
|
|
TestIngredient("⅔ cup unsweetened flaked coconut", 0.667, "cup", "coconut", "unsweetened flaked"),
|
|
|
|
|
TestIngredient("⅓ cup panko bread crumbs", 0.333, "cup", "panko bread crumbs", ""),
|
|
|
|
|
# Small Fraction Tests - PR #1369
|
|
|
|
|
# Reported error is was for 1/8 - new lowest expected threshold is 1/32
|
|
|
|
|
TestIngredient("1/8 cup all-purpose flour", 0.125, "cup", "all-purpose flour", ""),
|
2022-06-10 19:01:14 -08:00
|
|
|
|
TestIngredient("1/32 cup all-purpose flour", 0.031, "cup", "all-purpose flour", ""),
|
2021-10-09 13:08:23 -08:00
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.skipif(not crf_exists(), reason="CRF++ not installed")
|
|
|
|
|
def test_nlp_parser():
|
|
|
|
|
models: list[CRFIngredient] = convert_list_to_crf_model([x.input for x in test_ingredients])
|
|
|
|
|
|
2022-09-25 23:17:27 +00:00
|
|
|
|
# Iterate over models and test_ingredients to gather
|
2021-10-09 13:08:23 -08:00
|
|
|
|
for model, test_ingredient in zip(models, test_ingredients):
|
2022-06-10 19:01:14 -08:00
|
|
|
|
assert round(float(sum(Fraction(s) for s in model.qty.split())), 3) == pytest.approx(test_ingredient.quantity)
|
2021-10-09 13:08:23 -08:00
|
|
|
|
|
|
|
|
|
assert model.comment == test_ingredient.comments
|
|
|
|
|
assert model.name == test_ingredient.food
|
|
|
|
|
assert model.unit == test_ingredient.unit
|
2021-10-16 16:06:13 -08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_brute_parser():
|
|
|
|
|
# input: (quantity, unit, food, comments)
|
|
|
|
|
expectations = {
|
|
|
|
|
# Dutch
|
|
|
|
|
"1 theelepel koffie": (1, "theelepel", "koffie", ""),
|
|
|
|
|
"3 theelepels koffie": (3, "theelepels", "koffie", ""),
|
|
|
|
|
"1 eetlepel tarwe": (1, "eetlepel", "tarwe", ""),
|
|
|
|
|
"20 eetlepels bloem": (20, "eetlepels", "bloem", ""),
|
|
|
|
|
"1 mespunt kaneel": (1, "mespunt", "kaneel", ""),
|
|
|
|
|
"1 snuf(je) zout": (1, "snuf(je)", "zout", ""),
|
|
|
|
|
"2 tbsp minced cilantro, leaves and stems": (2, "tbsp", "minced cilantro", "leaves and stems"),
|
|
|
|
|
"1 large yellow onion, coarsely chopped": (1, "large", "yellow onion", "coarsely chopped"),
|
|
|
|
|
"1 1/2 tsp garam masala": (1.5, "tsp", "garam masala", ""),
|
|
|
|
|
"2 cups mango chunks, (2 large mangoes) (fresh or frozen)": (
|
|
|
|
|
2,
|
|
|
|
|
"cups",
|
|
|
|
|
"mango chunks, (2 large mangoes)",
|
|
|
|
|
"fresh or frozen",
|
|
|
|
|
),
|
|
|
|
|
}
|
|
|
|
|
parser = get_parser(RegisteredParser.brute)
|
|
|
|
|
|
|
|
|
|
for key, val in expectations.items():
|
|
|
|
|
parsed = parser.parse_one(key)
|
|
|
|
|
|
|
|
|
|
assert parsed.ingredient.quantity == val[0]
|
|
|
|
|
assert parsed.ingredient.unit.name == val[1]
|
|
|
|
|
assert parsed.ingredient.food.name == val[2]
|
|
|
|
|
assert parsed.ingredient.note in {val[3], None}
|