Skip to main content
Glama
cbcoutinho

Nextcloud MCP Server

by cbcoutinho
test_cookbook_api.py12.5 kB
import logging import httpx import pytest from nextcloud_mcp_server.client.cookbook import CookbookClient from tests.client.conftest import ( create_mock_error_response, create_mock_recipe_list_response, create_mock_recipe_response, create_mock_response, ) logger = logging.getLogger(__name__) # Mark all tests in this module as unit tests pytestmark = pytest.mark.unit async def test_cookbook_version(mocker): """Test that get_version correctly parses the API response.""" mock_response = create_mock_response( status_code=200, json_data={ "cookbook_version": "1.0.0", "api_version": "1.0.0", }, ) mock_client = mocker.AsyncMock(spec=httpx.AsyncClient) mock_make_request = mocker.patch.object( CookbookClient, "_make_request", return_value=mock_response ) client = CookbookClient(mock_client, "testuser") version_data = await client.get_version() assert "cookbook_version" in version_data assert "api_version" in version_data assert version_data["cookbook_version"] == "1.0.0" mock_make_request.assert_called_once_with("GET", "/apps/cookbook/api/version") async def test_cookbook_config(mocker): """Test that get_config correctly parses the API response.""" mock_response = create_mock_response( status_code=200, json_data={ "folder": "/recipes", "update_interval": 60, "print_image": True, }, ) mock_client = mocker.AsyncMock(spec=httpx.AsyncClient) mock_make_request = mocker.patch.object( CookbookClient, "_make_request", return_value=mock_response ) client = CookbookClient(mock_client, "testuser") config_data = await client.get_config() assert isinstance(config_data, dict) assert config_data["folder"] == "/recipes" mock_make_request.assert_called_once_with("GET", "/apps/cookbook/api/v1/config") async def test_cookbook_list_recipes(mocker): """Test that list_recipes correctly parses the API response.""" mock_response = create_mock_recipe_list_response( recipes=[ {"id": 1, "name": "Recipe 1", "recipeCategory": "Test"}, {"id": 2, "name": "Recipe 2", "recipeCategory": "Test"}, ] ) mock_client = mocker.AsyncMock(spec=httpx.AsyncClient) mock_make_request = mocker.patch.object( CookbookClient, "_make_request", return_value=mock_response ) client = CookbookClient(mock_client, "testuser") recipes = await client.list_recipes() assert isinstance(recipes, list) assert len(recipes) == 2 assert recipes[0]["name"] == "Recipe 1" mock_make_request.assert_called_once_with("GET", "/apps/cookbook/api/v1/recipes") async def test_cookbook_create_recipe(mocker): """Test that create_recipe correctly parses the API response.""" # Create_recipe returns just the recipe ID mock_response = create_mock_response(status_code=200, json_data=123) mock_client = mocker.AsyncMock(spec=httpx.AsyncClient) mock_make_request = mocker.patch.object( CookbookClient, "_make_request", return_value=mock_response ) client = CookbookClient(mock_client, "testuser") recipe_data = { "name": "Test Recipe", "description": "Test description", "recipeIngredient": ["100g flour"], "recipeInstructions": ["Mix ingredients"], } recipe_id = await client.create_recipe(recipe_data) assert recipe_id == 123 mock_make_request.assert_called_once_with( "POST", "/apps/cookbook/api/v1/recipes", json=recipe_data ) async def test_cookbook_get_recipe(mocker): """Test that get_recipe correctly parses the API response.""" mock_response = create_mock_recipe_response( recipe_id=123, name="Test Recipe", description="Test description", recipe_category="Test", keywords="test,integration", recipe_yield=4, recipeIngredient=["100g flour", "2 eggs"], recipeInstructions=["Mix ingredients", "Cook"], ) mock_client = mocker.AsyncMock(spec=httpx.AsyncClient) mock_make_request = mocker.patch.object( CookbookClient, "_make_request", return_value=mock_response ) client = CookbookClient(mock_client, "testuser") recipe = await client.get_recipe(recipe_id=123) assert recipe["id"] == 123 assert recipe["name"] == "Test Recipe" assert recipe["description"] == "Test description" assert len(recipe["recipeIngredient"]) == 2 assert len(recipe["recipeInstructions"]) == 2 mock_make_request.assert_called_once_with( "GET", "/apps/cookbook/api/v1/recipes/123" ) async def test_cookbook_update_recipe(mocker): """Test that update_recipe correctly parses the API response.""" # Update_recipe returns the recipe ID mock_response = create_mock_response(status_code=200, json_data=123) mock_client = mocker.AsyncMock(spec=httpx.AsyncClient) mock_make_request = mocker.patch.object( CookbookClient, "_make_request", return_value=mock_response ) client = CookbookClient(mock_client, "testuser") updated_data = { "name": "Updated Recipe", "description": "Updated description", "recipeIngredient": ["100g flour", "2 eggs", "200ml milk"], "recipeInstructions": ["Mix ingredients", "Cook", "Serve"], } updated_id = await client.update_recipe(recipe_id=123, recipe_data=updated_data) assert updated_id == 123 mock_make_request.assert_called_once_with( "PUT", "/apps/cookbook/api/v1/recipes/123", json=updated_data ) async def test_cookbook_delete_recipe(mocker): """Test that delete_recipe correctly parses the API response.""" mock_response = create_mock_response( status_code=200, json_data="Recipe deleted successfully" ) mock_client = mocker.AsyncMock(spec=httpx.AsyncClient) mock_make_request = mocker.patch.object( CookbookClient, "_make_request", return_value=mock_response ) client = CookbookClient(mock_client, "testuser") result = await client.delete_recipe(recipe_id=123) assert isinstance(result, str) assert "deleted" in result.lower() mock_make_request.assert_called_once_with( "DELETE", "/apps/cookbook/api/v1/recipes/123" ) async def test_cookbook_delete_nonexistent_recipe(mocker): """Test that deleting a non-existent recipe raises HTTPStatusError.""" error_response = create_mock_error_response(404, "Recipe not found") mock_client = mocker.AsyncMock(spec=httpx.AsyncClient) mock_make_request = mocker.patch.object(CookbookClient, "_make_request") mock_make_request.side_effect = httpx.HTTPStatusError( "404 Not Found", request=httpx.Request("DELETE", "http://test.local"), response=error_response, ) client = CookbookClient(mock_client, "testuser") with pytest.raises(httpx.HTTPStatusError) as excinfo: await client.delete_recipe(recipe_id=999999999) assert excinfo.value.response.status_code == 404 async def test_cookbook_search_recipes(mocker): """Test that search_recipes correctly parses the API response.""" mock_response = create_mock_recipe_list_response( recipes=[ {"id": 1, "name": "Test Recipe 1", "keywords": "test,search"}, {"id": 2, "name": "Test Recipe 2", "keywords": "test,search"}, ] ) mock_client = mocker.AsyncMock(spec=httpx.AsyncClient) mock_make_request = mocker.patch.object( CookbookClient, "_make_request", return_value=mock_response ) client = CookbookClient(mock_client, "testuser") search_results = await client.search_recipes("test") assert isinstance(search_results, list) assert len(search_results) == 2 # Verify URL encoding happened mock_make_request.assert_called_once() call_args = mock_make_request.call_args[0] assert "/apps/cookbook/api/v1/search/" in call_args[1] async def test_cookbook_list_categories(mocker): """Test that list_categories correctly parses the API response.""" mock_response = create_mock_response( status_code=200, json_data=[ {"name": "Desserts", "recipe_count": 5}, {"name": "Main Course", "recipe_count": 10}, ], ) mock_client = mocker.AsyncMock(spec=httpx.AsyncClient) mock_make_request = mocker.patch.object( CookbookClient, "_make_request", return_value=mock_response ) client = CookbookClient(mock_client, "testuser") categories = await client.list_categories() assert isinstance(categories, list) assert len(categories) == 2 assert categories[0]["name"] == "Desserts" assert categories[0]["recipe_count"] == 5 mock_make_request.assert_called_once_with("GET", "/apps/cookbook/api/v1/categories") async def test_cookbook_get_recipes_in_category(mocker): """Test that get_recipes_in_category correctly parses the API response.""" mock_response = create_mock_recipe_list_response( recipes=[ {"id": 1, "name": "Recipe 1", "recipeCategory": "Desserts"}, {"id": 2, "name": "Recipe 2", "recipeCategory": "Desserts"}, ] ) mock_client = mocker.AsyncMock(spec=httpx.AsyncClient) mock_make_request = mocker.patch.object( CookbookClient, "_make_request", return_value=mock_response ) client = CookbookClient(mock_client, "testuser") recipes_in_category = await client.get_recipes_in_category("Desserts") assert isinstance(recipes_in_category, list) assert len(recipes_in_category) == 2 assert recipes_in_category[0]["recipeCategory"] == "Desserts" # Verify URL encoding happened mock_make_request.assert_called_once() call_args = mock_make_request.call_args[0] assert "/apps/cookbook/api/v1/category/" in call_args[1] async def test_cookbook_list_keywords(mocker): """Test that list_keywords correctly parses the API response.""" mock_response = create_mock_response( status_code=200, json_data=[ {"name": "vegetarian", "recipe_count": 15}, {"name": "quick", "recipe_count": 8}, ], ) mock_client = mocker.AsyncMock(spec=httpx.AsyncClient) mock_make_request = mocker.patch.object( CookbookClient, "_make_request", return_value=mock_response ) client = CookbookClient(mock_client, "testuser") keywords = await client.list_keywords() assert isinstance(keywords, list) assert len(keywords) == 2 assert keywords[0]["name"] == "vegetarian" assert keywords[0]["recipe_count"] == 15 mock_make_request.assert_called_once_with("GET", "/apps/cookbook/api/v1/keywords") async def test_cookbook_get_recipes_with_keywords(mocker): """Test that get_recipes_with_keywords correctly parses the API response.""" mock_response = create_mock_recipe_list_response( recipes=[ {"id": 1, "name": "Recipe 1", "keywords": "vegetarian,quick"}, {"id": 2, "name": "Recipe 2", "keywords": "vegetarian,healthy"}, ] ) mock_client = mocker.AsyncMock(spec=httpx.AsyncClient) mock_make_request = mocker.patch.object( CookbookClient, "_make_request", return_value=mock_response ) client = CookbookClient(mock_client, "testuser") recipes_with_keywords = await client.get_recipes_with_keywords( ["vegetarian", "quick"] ) assert isinstance(recipes_with_keywords, list) assert len(recipes_with_keywords) == 2 # Verify URL encoding and keyword joining happened mock_make_request.assert_called_once() call_args = mock_make_request.call_args[0] assert "/apps/cookbook/api/v1/tags/" in call_args[1] async def test_cookbook_reindex(mocker): """Test that reindex correctly parses the API response.""" mock_response = create_mock_response( status_code=200, json_data="Reindex completed successfully", ) mock_client = mocker.AsyncMock(spec=httpx.AsyncClient) mock_make_request = mocker.patch.object( CookbookClient, "_make_request", return_value=mock_response ) client = CookbookClient(mock_client, "testuser") result = await client.reindex() assert isinstance(result, str) assert "reindex" in result.lower() or "completed" in result.lower() mock_make_request.assert_called_once_with("POST", "/apps/cookbook/api/v1/reindex")

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/cbcoutinho/nextcloud-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server