"""
Simplified tests for organizers and parser tools focusing on code coverage.
"""
import json
import pytest
from unittest.mock import MagicMock, patch
from src.tools.organizers import (
categories_update,
categories_delete,
tags_update,
tags_delete,
tools_update,
tools_delete
)
from src.tools.parser import (
parser_ingredient,
parser_ingredients_batch
)
def create_mock_client(get_value=None, post_value=None):
"""Helper to create a mocked MealieClient."""
mock = MagicMock()
mock.__enter__ = MagicMock(return_value=mock)
mock.__exit__ = MagicMock(return_value=None)
if get_value is not None:
mock.get.return_value = get_value
if post_value is not None:
mock.post.return_value = post_value
return mock
class TestOrganizers:
"""Test organizer operations (categories, tags, tools)."""
def test_categories_update(self):
"""Test updating a category."""
mock_client = MagicMock()
mock_client.__enter__ = MagicMock(return_value=mock_client)
mock_client.__exit__ = MagicMock(return_value=None)
mock_client.patch.return_value = {"id": "1", "name": "Updated"}
with patch('src.tools.organizers.MealieClient', return_value=mock_client):
result = categories_update("cat-1", name="Updated")
data = json.loads(result)
assert isinstance(data, dict)
def test_categories_delete(self):
"""Test deleting a category."""
mock_client = MagicMock()
mock_client.__enter__ = MagicMock(return_value=mock_client)
mock_client.__exit__ = MagicMock(return_value=None)
mock_client.delete.return_value = None
with patch('src.tools.organizers.MealieClient', return_value=mock_client):
result = categories_delete("cat-1")
data = json.loads(result)
assert isinstance(data, dict)
def test_tags_update(self):
"""Test updating a tag."""
mock_client = MagicMock()
mock_client.__enter__ = MagicMock(return_value=mock_client)
mock_client.__exit__ = MagicMock(return_value=None)
mock_client.patch.return_value = {"id": "1", "name": "Updated"}
with patch('src.tools.organizers.MealieClient', return_value=mock_client):
result = tags_update("tag-1", name="Updated")
data = json.loads(result)
assert isinstance(data, dict)
def test_tags_delete(self):
"""Test deleting a tag."""
mock_client = MagicMock()
mock_client.__enter__ = MagicMock(return_value=mock_client)
mock_client.__exit__ = MagicMock(return_value=None)
mock_client.delete.return_value = None
with patch('src.tools.organizers.MealieClient', return_value=mock_client):
result = tags_delete("tag-1")
data = json.loads(result)
assert isinstance(data, dict)
def test_tools_update(self):
"""Test updating a tool."""
mock_client = MagicMock()
mock_client.__enter__ = MagicMock(return_value=mock_client)
mock_client.__exit__ = MagicMock(return_value=None)
mock_client.patch.return_value = {"id": "1", "name": "Updated"}
with patch('src.tools.organizers.MealieClient', return_value=mock_client):
result = tools_update("tool-1", name="Updated")
data = json.loads(result)
assert isinstance(data, dict)
def test_tools_delete(self):
"""Test deleting a tool."""
mock_client = MagicMock()
mock_client.__enter__ = MagicMock(return_value=mock_client)
mock_client.__exit__ = MagicMock(return_value=None)
mock_client.delete.return_value = None
with patch('src.tools.organizers.MealieClient', return_value=mock_client):
result = tools_delete("tool-1")
data = json.loads(result)
assert isinstance(data, dict)
class TestParser:
"""Test ingredient parser operations."""
def test_parse_ingredient(self):
"""Test parsing a single ingredient."""
mock_client = create_mock_client(post_value={
"input": "2 cups flour",
"ingredient": {
"quantity": 2.0,
"unit": "cup",
"food": "flour"
}
})
with patch('src.tools.parser.MealieClient', return_value=mock_client):
result = parser_ingredient("2 cups flour")
data = json.loads(result)
assert isinstance(data, dict)
def test_parse_ingredients_batch(self):
"""Test parsing multiple ingredients."""
mock_client = create_mock_client(post_value=[
{"input": "2 cups flour", "ingredient": {"quantity": 2.0}},
{"input": "1 tsp salt", "ingredient": {"quantity": 1.0}}
])
with patch('src.tools.parser.MealieClient', return_value=mock_client):
result = parser_ingredients_batch(["2 cups flour", "1 tsp salt"])
data = json.loads(result)
assert isinstance(data, (dict, list))
def test_parse_ingredient_with_custom_parser(self):
"""Test parsing ingredient with custom parser."""
mock_client = create_mock_client(post_value={
"input": "1/2 cup butter",
"ingredient": {"quantity": 0.5, "unit": "cup", "food": "butter"}
})
with patch('src.tools.parser.MealieClient', return_value=mock_client):
result = parser_ingredient("1/2 cup butter", parser="brute")
data = json.loads(result)
assert isinstance(data, dict)
def test_parse_ingredient_complex(self):
"""Test parsing complex ingredient string."""
mock_client = create_mock_client(post_value={
"input": "2 cups all-purpose flour, sifted",
"ingredient": {
"quantity": 2.0,
"unit": "cup",
"food": "all-purpose flour",
"note": "sifted"
}
})
with patch('src.tools.parser.MealieClient', return_value=mock_client):
result = parser_ingredient("2 cups all-purpose flour, sifted")
data = json.loads(result)
assert isinstance(data, dict)
def test_parse_ingredients_batch_large(self):
"""Test parsing large batch of ingredients."""
ingredients = [
"2 cups flour",
"1 tsp salt",
"1/2 cup butter",
"3 eggs",
"1 cup milk"
]
mock_response = [
{"input": ing, "ingredient": {"quantity": 1.0}}
for ing in ingredients
]
mock_client = create_mock_client(post_value=mock_response)
with patch('src.tools.parser.MealieClient', return_value=mock_client):
result = parser_ingredients_batch(ingredients)
data = json.loads(result)
assert isinstance(data, (dict, list))
def test_parse_ingredients_batch_with_parser(self):
"""Test batch parsing with custom parser."""
mock_client = create_mock_client(post_value=[
{"input": "2 cups flour", "ingredient": {"quantity": 2.0}},
{"input": "1 tsp salt", "ingredient": {"quantity": 1.0}}
])
with patch('src.tools.parser.MealieClient', return_value=mock_client):
result = parser_ingredients_batch(
["2 cups flour", "1 tsp salt"],
parser="nlp"
)
data = json.loads(result)
assert isinstance(data, (dict, list))
class TestErrorHandling:
"""Test error handling across modules."""
def test_organizers_api_error(self):
"""Test organizers API error handling."""
from src.client import MealieAPIError
mock_client = MagicMock()
mock_client.__enter__ = MagicMock(return_value=mock_client)
mock_client.__exit__ = MagicMock(return_value=None)
mock_client.patch.side_effect = MealieAPIError(
"Error", status_code=500, response_body="Error"
)
with patch('src.tools.organizers.MealieClient', return_value=mock_client):
result = categories_update("cat-1", name="Test")
data = json.loads(result)
assert "error" in data
def test_parser_api_error(self):
"""Test parser API error handling."""
from src.client import MealieAPIError
mock_client = MagicMock()
mock_client.__enter__ = MagicMock(return_value=mock_client)
mock_client.__exit__ = MagicMock(return_value=None)
mock_client.post.side_effect = MealieAPIError(
"Error", status_code=500, response_body="Error"
)
with patch('src.tools.parser.MealieClient', return_value=mock_client):
result = parser_ingredient("test")
data = json.loads(result)
assert "error" in data
def test_tags_update_error(self):
"""Test tags_update error handling."""
from src.client import MealieAPIError
mock_client = MagicMock()
mock_client.__enter__ = MagicMock(return_value=mock_client)
mock_client.__exit__ = MagicMock(return_value=None)
mock_client.patch.side_effect = MealieAPIError(
"Error", status_code=400, response_body="Bad request"
)
with patch('src.tools.organizers.MealieClient', return_value=mock_client):
result = tags_update("tag-1", name="Test")
data = json.loads(result)
assert "error" in data
def test_tools_update_error(self):
"""Test tools_update error handling."""
from src.client import MealieAPIError
mock_client = MagicMock()
mock_client.__enter__ = MagicMock(return_value=mock_client)
mock_client.__exit__ = MagicMock(return_value=None)
mock_client.patch.side_effect = MealieAPIError(
"Error", status_code=404, response_body="Not found"
)
with patch('src.tools.organizers.MealieClient', return_value=mock_client):
result = tools_update("tool-1", name="Test")
data = json.loads(result)
assert "error" in data
def test_categories_delete_error(self):
"""Test categories_delete error handling."""
from src.client import MealieAPIError
mock_client = MagicMock()
mock_client.__enter__ = MagicMock(return_value=mock_client)
mock_client.__exit__ = MagicMock(return_value=None)
mock_client.delete_category.side_effect = MealieAPIError(
"Error", status_code=409, response_body="Conflict"
)
with patch('src.tools.organizers.MealieClient', return_value=mock_client):
result = categories_delete("cat-1")
data = json.loads(result)
assert "error" in data
def test_parser_batch_error(self):
"""Test parser_ingredients_batch error handling."""
from src.client import MealieAPIError
mock_client = MagicMock()
mock_client.__enter__ = MagicMock(return_value=mock_client)
mock_client.__exit__ = MagicMock(return_value=None)
mock_client.post.side_effect = MealieAPIError(
"Batch error", status_code=500, response_body="Server error"
)
with patch('src.tools.parser.MealieClient', return_value=mock_client):
result = parser_ingredients_batch(["flour", "salt"])
data = json.loads(result)
assert "error" in data
class TestOrganizersAdvanced:
"""Test advanced organizer scenarios."""
def test_categories_update_with_slug(self):
"""Test updating category with slug."""
mock_client = MagicMock()
mock_client.__enter__ = MagicMock(return_value=mock_client)
mock_client.__exit__ = MagicMock(return_value=None)
mock_client.patch.return_value = {
"id": "1",
"name": "Updated",
"slug": "updated-slug"
}
with patch('src.tools.organizers.MealieClient', return_value=mock_client):
result = categories_update("cat-1", name="Updated", slug="updated-slug")
data = json.loads(result)
assert isinstance(data, dict)
def test_tags_update_slug_only(self):
"""Test updating tag slug only."""
mock_client = MagicMock()
mock_client.__enter__ = MagicMock(return_value=mock_client)
mock_client.__exit__ = MagicMock(return_value=None)
mock_client.patch.return_value = {
"id": "1",
"name": "Tag",
"slug": "new-slug"
}
with patch('src.tools.organizers.MealieClient', return_value=mock_client):
result = tags_update("tag-1", slug="new-slug")
data = json.loads(result)
assert isinstance(data, dict)
def test_tools_update_name_only(self):
"""Test updating tool name only."""
mock_client = MagicMock()
mock_client.__enter__ = MagicMock(return_value=mock_client)
mock_client.__exit__ = MagicMock(return_value=None)
mock_client.patch.return_value = {
"id": "1",
"name": "New Name"
}
with patch('src.tools.organizers.MealieClient', return_value=mock_client):
result = tools_update("tool-1", name="New Name")
data = json.loads(result)
assert isinstance(data, dict)
class TestParserMoreCases:
"""Additional parser tests for coverage."""
def test_parse_ingredient_empty_response(self):
"""Test parsing ingredient with empty response."""
mock_client = create_mock_client(post_value={})
with patch('src.tools.parser.MealieClient', return_value=mock_client):
result = parser_ingredient("empty test")
data = json.loads(result)
assert isinstance(data, dict)
def test_parse_ingredients_batch_empty_list(self):
"""Test batch parsing with empty list."""
mock_client = create_mock_client(post_value=[])
with patch('src.tools.parser.MealieClient', return_value=mock_client):
result = parser_ingredients_batch([])
data = json.loads(result)
assert isinstance(data, (dict, list))
def test_parse_ingredients_single_item_batch(self):
"""Test batch parsing with single item."""
mock_client = create_mock_client(post_value=[
{"input": "1 cup flour", "ingredient": {"quantity": 1.0}}
])
with patch('src.tools.parser.MealieClient', return_value=mock_client):
result = parser_ingredients_batch(["1 cup flour"])
data = json.loads(result)
assert isinstance(data, (dict, list))
def test_parse_ingredient_with_note(self):
"""Test parsing ingredient with note field."""
mock_client = create_mock_client(post_value={
"input": "2 cups flour, sifted",
"ingredient": {
"quantity": 2.0,
"unit": "cup",
"food": "flour",
"note": "sifted"
}
})
with patch('src.tools.parser.MealieClient', return_value=mock_client):
result = parser_ingredient("2 cups flour, sifted", parser="nlp")
data = json.loads(result)
assert isinstance(data, dict)
def test_parse_ingredient_unexpected_error(self):
"""Test parser unexpected error handling."""
mock_client = MagicMock()
mock_client.__enter__ = MagicMock(return_value=mock_client)
mock_client.__exit__ = MagicMock(return_value=None)
mock_client.post.side_effect = ValueError("Unexpected error")
with patch('src.tools.parser.MealieClient', return_value=mock_client):
result = parser_ingredient("test")
data = json.loads(result)
assert "error" in data
def test_parse_ingredients_batch_unexpected_error(self):
"""Test batch parser unexpected error handling."""
mock_client = MagicMock()
mock_client.__enter__ = MagicMock(return_value=mock_client)
mock_client.__exit__ = MagicMock(return_value=None)
mock_client.post.side_effect = TypeError("Type error")
with patch('src.tools.parser.MealieClient', return_value=mock_client):
result = parser_ingredients_batch(["test1", "test2"])
data = json.loads(result)
assert "error" in data
class TestOrganizersFinalPush:
"""Final organizers tests to reach 50% coverage."""
def test_categories_update_unexpected_error(self):
"""Test categories_update unexpected error."""
mock_client = MagicMock()
mock_client.__enter__ = MagicMock(return_value=mock_client)
mock_client.__exit__ = MagicMock(return_value=None)
mock_client.patch.side_effect = ValueError("Value error")
with patch('src.tools.organizers.MealieClient', return_value=mock_client):
result = categories_update("cat-1", name="Test")
data = json.loads(result)
assert "error" in data
def test_tags_update_unexpected_error(self):
"""Test tags_update unexpected error."""
mock_client = MagicMock()
mock_client.__enter__ = MagicMock(return_value=mock_client)
mock_client.__exit__ = MagicMock(return_value=None)
mock_client.patch.side_effect = TypeError("Type error")
with patch('src.tools.organizers.MealieClient', return_value=mock_client):
result = tags_update("tag-1", name="Test")
data = json.loads(result)
assert "error" in data
def test_tools_update_unexpected_error(self):
"""Test tools_update unexpected error."""
mock_client = MagicMock()
mock_client.__enter__ = MagicMock(return_value=mock_client)
mock_client.__exit__ = MagicMock(return_value=None)
mock_client.patch.side_effect = RuntimeError("Runtime error")
with patch('src.tools.organizers.MealieClient', return_value=mock_client):
result = tools_update("tool-1", name="Test")
data = json.loads(result)
assert "error" in data
def test_tags_delete_unexpected_error(self):
"""Test tags_delete unexpected error."""
mock_client = MagicMock()
mock_client.__enter__ = MagicMock(return_value=mock_client)
mock_client.__exit__ = MagicMock(return_value=None)
mock_client.delete_tag.side_effect = ValueError("Value error")
with patch('src.tools.organizers.MealieClient', return_value=mock_client):
result = tags_delete("tag-1")
data = json.loads(result)
assert "error" in data
def test_tools_delete_unexpected_error(self):
"""Test tools_delete unexpected error."""
mock_client = MagicMock()
mock_client.__enter__ = MagicMock(return_value=mock_client)
mock_client.__exit__ = MagicMock(return_value=None)
mock_client.delete_tool.side_effect = TypeError("Type error")
with patch('src.tools.organizers.MealieClient', return_value=mock_client):
result = tools_delete("tool-1")
data = json.loads(result)
assert "error" in data
def test_categories_delete_unexpected_error(self):
"""Test categories_delete unexpected error."""
mock_client = MagicMock()
mock_client.__enter__ = MagicMock(return_value=mock_client)
mock_client.__exit__ = MagicMock(return_value=None)
mock_client.delete_category.side_effect = RuntimeError("Runtime error")
with patch('src.tools.organizers.MealieClient', return_value=mock_client):
result = categories_delete("cat-1")
data = json.loads(result)
assert "error" in data