Skip to main content
Glama
cbcoutinho

Nextcloud MCP Server

by cbcoutinho
test_webdav_operations.py9.96 kB
"""Integration tests for WebDAV operations.""" import logging import uuid import pytest from httpx import HTTPStatusError from nextcloud_mcp_server.client import NextcloudClient logger = logging.getLogger(__name__) # Mark all tests in this module as integration tests pytestmark = pytest.mark.integration @pytest.fixture async def test_base_path(nc_client: NextcloudClient): """Base path for test files/directories.""" test_dir = f"mcp_test_{uuid.uuid4().hex[:8]}" await nc_client.webdav.create_directory(test_dir) yield test_dir await nc_client.webdav.delete_resource(test_dir) async def test_create_and_delete_directory( nc_client: NextcloudClient, test_base_path: str ): """Test creating and deleting directories.""" test_dir = f"{test_base_path}/test_directory" try: # Create directory result = await nc_client.webdav.create_directory(test_dir) assert result["status_code"] == 201 # Created logger.info(f"Created directory: {test_dir}") # Verify directory exists by listing parent parent_listing = await nc_client.webdav.list_directory(test_base_path) dir_names = [item["name"] for item in parent_listing] assert "test_directory" in dir_names # Delete directory delete_result = await nc_client.webdav.delete_resource(test_dir) assert delete_result["status_code"] in [204, 404] # No Content or Not Found logger.info(f"Deleted directory: {test_dir}") finally: # Cleanup: ensure directory is deleted try: await nc_client.webdav.delete_resource(test_dir) except Exception: pass async def test_write_read_delete_file(nc_client: NextcloudClient, test_base_path: str): """Test writing, reading, and deleting files.""" test_file = f"{test_base_path}/test_file.txt" test_content = f"Test content {uuid.uuid4().hex}" try: # Create base directory first await nc_client.webdav.create_directory(test_base_path) # Write file write_result = await nc_client.webdav.write_file( test_file, test_content.encode("utf-8"), content_type="text/plain" ) assert write_result["status_code"] in [200, 201, 204] # Success codes logger.info(f"Wrote file: {test_file}") # Read file back content, content_type = await nc_client.webdav.read_file(test_file) assert content.decode("utf-8") == test_content assert "text/plain" in content_type logger.info(f"Read file: {test_file}") # Verify file appears in directory listing listing = await nc_client.webdav.list_directory(test_base_path) file_names = [item["name"] for item in listing] assert "test_file.txt" in file_names # Delete file delete_result = await nc_client.webdav.delete_resource(test_file) assert delete_result["status_code"] in [204, 404] # No Content or Not Found logger.info(f"Deleted file: {test_file}") finally: # Cleanup try: await nc_client.webdav.delete_resource(test_file) await nc_client.webdav.delete_resource(test_base_path) except Exception: pass async def test_list_directory_empty_and_populated( nc_client: NextcloudClient, test_base_path: str ): """Test listing empty and populated directories.""" try: # Create base directory await nc_client.webdav.create_directory(test_base_path) # List empty directory empty_listing = await nc_client.webdav.list_directory(test_base_path) assert isinstance(empty_listing, list) assert len(empty_listing) == 0 logger.info(f"Empty directory listing: {len(empty_listing)} items") # Add some files and directories await nc_client.webdav.create_directory(f"{test_base_path}/subdir1") await nc_client.webdav.create_directory(f"{test_base_path}/subdir2") await nc_client.webdav.write_file( f"{test_base_path}/file1.txt", b"content1", content_type="text/plain" ) await nc_client.webdav.write_file( f"{test_base_path}/file2.md", b"# Markdown content", content_type="text/markdown", ) # List populated directory populated_listing = await nc_client.webdav.list_directory(test_base_path) assert len(populated_listing) == 4 # 2 dirs + 2 files # Check that we have both files and directories names = [item["name"] for item in populated_listing] assert "subdir1" in names assert "subdir2" in names assert "file1.txt" in names assert "file2.md" in names # Check metadata is present for item in populated_listing: assert "name" in item assert "path" in item assert "is_directory" in item assert "size" in item assert "content_type" in item assert "last_modified" in item logger.info(f"Populated directory listing: {len(populated_listing)} items") finally: # Cleanup try: await nc_client.webdav.delete_resource(f"{test_base_path}/file1.txt") await nc_client.webdav.delete_resource(f"{test_base_path}/file2.md") await nc_client.webdav.delete_resource(f"{test_base_path}/subdir1") await nc_client.webdav.delete_resource(f"{test_base_path}/subdir2") await nc_client.webdav.delete_resource(test_base_path) except Exception: pass async def test_read_nonexistent_file(nc_client: NextcloudClient): """Test reading a file that doesn't exist.""" nonexistent_file = f"nonexistent_{uuid.uuid4().hex}.txt" with pytest.raises(HTTPStatusError) as exc_info: await nc_client.webdav.read_file(nonexistent_file) assert exc_info.value.response.status_code == 404 logger.info(f"Correctly got 404 for nonexistent file: {nonexistent_file}") async def test_delete_nonexistent_resource(nc_client: NextcloudClient): """Test deleting a resource that doesn't exist.""" nonexistent_resource = f"nonexistent_{uuid.uuid4().hex}" result = await nc_client.webdav.delete_resource(nonexistent_resource) assert result["status_code"] == 404 logger.info(f"Correctly got 404 for nonexistent resource: {nonexistent_resource}") async def test_create_nested_directories( nc_client: NextcloudClient, test_base_path: str ): """Test creating nested directory structures.""" nested_path = f"{test_base_path}/level1/level2/level3" try: # Create nested directories (should create parent directories automatically) result = await nc_client.webdav.create_directory(nested_path, True) assert result["status_code"] == 201 # Verify the structure was created level1_listing = await nc_client.webdav.list_directory( f"{test_base_path}/level1" ) assert len(level1_listing) == 1 assert level1_listing[0]["name"] == "level2" assert level1_listing[0]["is_directory"] is True level2_listing = await nc_client.webdav.list_directory( f"{test_base_path}/level1/level2" ) assert len(level2_listing) == 1 assert level2_listing[0]["name"] == "level3" assert level2_listing[0]["is_directory"] is True logger.info(f"Created nested directory structure: {nested_path}") finally: # Cleanup - delete from deepest to shallowest try: await nc_client.webdav.delete_resource(nested_path) await nc_client.webdav.delete_resource(f"{test_base_path}/level1/level2") await nc_client.webdav.delete_resource(f"{test_base_path}/level1") except Exception: pass async def test_overwrite_existing_file(nc_client: NextcloudClient, test_base_path: str): """Test overwriting an existing file.""" test_file = f"{test_base_path}/overwrite_test.txt" original_content = "Original content" new_content = "New content after overwrite" try: # Create base directory await nc_client.webdav.create_directory(test_base_path) # Write original file await nc_client.webdav.write_file( test_file, original_content.encode("utf-8"), content_type="text/plain" ) # Verify original content content, _ = await nc_client.webdav.read_file(test_file) assert content.decode("utf-8") == original_content # Overwrite with new content overwrite_result = await nc_client.webdav.write_file( test_file, new_content.encode("utf-8"), content_type="text/plain" ) assert overwrite_result["status_code"] in [200, 204] # OK or No Content # Verify new content content, _ = await nc_client.webdav.read_file(test_file) assert content.decode("utf-8") == new_content logger.info(f"Successfully overwrote file: {test_file}") finally: # Cleanup try: await nc_client.webdav.delete_resource(test_file) await nc_client.webdav.delete_resource(test_base_path) except Exception: pass async def test_list_root_directory(nc_client: NextcloudClient): """Test listing the root directory.""" root_listing = await nc_client.webdav.list_directory("") # Root directory should exist and be listable assert isinstance(root_listing, list) # Should have at least some default folders/files assert len(root_listing) >= 0 # Check structure of items for item in root_listing: assert "name" in item assert "path" in item assert "is_directory" in item assert "size" in item assert "content_type" in item assert "last_modified" in item logger.info(f"Root directory contains {len(root_listing)} items")

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