From 6ae30acc6f760ffcb6dfc1691609847ae10fe57e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 14 Apr 2026 23:02:56 +0000 Subject: [PATCH] address review: exclude bool from coercion, parameterize tests over all fields Agent-Logs-Url: https://github.com/dylanlangston/nextcloud-mcp-server/sessions/0360ab28-8913-450e-8c61-697e71ba9742 Co-authored-by: dylanlangston <16236219+dylanlangston@users.noreply.github.com> --- nextcloud_mcp_server/models/cookbook.py | 2 + tests/unit/test_nutrition_model.py | 89 ++++++++++++------------- 2 files changed, 45 insertions(+), 46 deletions(-) diff --git a/nextcloud_mcp_server/models/cookbook.py b/nextcloud_mcp_server/models/cookbook.py index d713358e..5452ca5f 100644 --- a/nextcloud_mcp_server/models/cookbook.py +++ b/nextcloud_mcp_server/models/cookbook.py @@ -63,6 +63,8 @@ class Nutrition(BaseModel): strings (e.g. '650 kcal') or numbers (e.g. 650). Nextcloud Cookbook stores whatever the source provided. """ + if isinstance(v, bool): + return v if isinstance(v, (int, float)): return str(v) return v diff --git a/tests/unit/test_nutrition_model.py b/tests/unit/test_nutrition_model.py index e2b7ba01..4e9870b4 100644 --- a/tests/unit/test_nutrition_model.py +++ b/tests/unit/test_nutrition_model.py @@ -1,67 +1,64 @@ """Unit tests for Nutrition model numeric coercion (issue #708).""" import pytest +from pydantic import ValidationError from nextcloud_mcp_server.models.cookbook import Nutrition - -@pytest.mark.unit -def test_nutrition_calories_accepts_string(): - """String calories values should be accepted as-is.""" - n = Nutrition(calories="650 kcal") - assert n.calories == "650 kcal" +NUTRITION_FIELDS = [ + "calories", + "carbohydrateContent", + "cholesterolContent", + "fatContent", + "fiberContent", + "proteinContent", + "saturatedFatContent", + "servingSize", + "sodiumContent", + "sugarContent", + "transFatContent", + "unsaturatedFatContent", +] @pytest.mark.unit -def test_nutrition_calories_coerces_int(): - """Integer calories values should be coerced to strings.""" - n = Nutrition(calories=260) - assert n.calories == "260" +@pytest.mark.parametrize("field", NUTRITION_FIELDS) +def test_nutrition_field_accepts_string(field: str): + """String values should be accepted as-is for every nutrition field.""" + n = Nutrition(**{field: "650 kcal"}) + assert getattr(n, field) == "650 kcal" @pytest.mark.unit -def test_nutrition_calories_coerces_float(): - """Float calories values should be coerced to strings.""" - n = Nutrition(calories=260.5) - assert n.calories == "260.5" +@pytest.mark.parametrize("field", NUTRITION_FIELDS) +def test_nutrition_field_coerces_int(field: str): + """Integer values should be coerced to strings for every nutrition field.""" + n = Nutrition(**{field: 260}) + assert getattr(n, field) == "260" @pytest.mark.unit -def test_nutrition_calories_accepts_none(): - """None calories should remain None.""" - n = Nutrition(calories=None) - assert n.calories is None +@pytest.mark.parametrize("field", NUTRITION_FIELDS) +def test_nutrition_field_coerces_float(field: str): + """Float values should be coerced to strings for every nutrition field.""" + n = Nutrition(**{field: 260.5}) + assert getattr(n, field) == "260.5" @pytest.mark.unit -def test_nutrition_all_fields_coerce_int(): - """All nutrition content fields should coerce integer values to strings.""" - n = Nutrition( - calories=260, - carbohydrateContent=30, - cholesterolContent=10, - fatContent=15, - fiberContent=5, - proteinContent=20, - saturatedFatContent=3, - servingSize=1, - sodiumContent=500, - sugarContent=8, - transFatContent=0, - unsaturatedFatContent=12, - ) - assert n.calories == "260" - assert n.carbohydrateContent == "30" - assert n.cholesterolContent == "10" - assert n.fatContent == "15" - assert n.fiberContent == "5" - assert n.proteinContent == "20" - assert n.saturatedFatContent == "3" - assert n.servingSize == "1" - assert n.sodiumContent == "500" - assert n.sugarContent == "8" - assert n.transFatContent == "0" - assert n.unsaturatedFatContent == "12" +@pytest.mark.parametrize("field", NUTRITION_FIELDS) +def test_nutrition_field_accepts_none(field: str): + """None should remain None for every nutrition field.""" + n = Nutrition(**{field: None}) + assert getattr(n, field) is None + + +@pytest.mark.unit +@pytest.mark.parametrize("field", NUTRITION_FIELDS) +def test_nutrition_field_rejects_bool(field: str): + """Boolean values should not be silently coerced to strings.""" + with pytest.raises(ValidationError): + Nutrition(**{field: True}) @pytest.mark.unit