diff --git a/CLAUDE.md b/CLAUDE.md index ed69773..0ffc880 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -102,13 +102,19 @@ Each Nextcloud app has a corresponding server module that: - **Important**: Integration tests run against live Docker containers. After making code changes to the MCP server, rebuild only the MCP container with `docker-compose up --build -d mcp` before running tests #### Testing Best Practices -- **Always restart MCP server** after code changes with `docker-compose up --build -d mcp` +- **MANDATORY: Always run tests after implementing features or fixing bugs** + - Run tests to completion before considering any task complete + - If tests require modifications to pass, ask for permission before proceeding + - Use `docker-compose up --build -d mcp` to rebuild MCP container after code changes - **Use existing fixtures** from `tests/conftest.py` to avoid duplicate setup work: - `nc_mcp_client` - MCP client session for tool/resource testing - `nc_client` - Direct NextcloudClient for setup/cleanup operations - `temporary_note` - Creates and cleans up test notes automatically - `temporary_addressbook` - Creates and cleans up test address books - `temporary_contact` - Creates and cleans up test contacts +- **Test specific functionality** after changes: + - For Notes changes: `uv run pytest tests/integration/test_mcp.py -k "notes" -v` + - For specific API changes: `uv run pytest tests/integration/test_notes_api.py -v` - **Avoid creating standalone test scripts** - use pytest with proper fixtures instead ### Configuration Files diff --git a/tests/integration/test_mcp.py b/tests/integration/test_mcp.py index c748973..136afeb 100644 --- a/tests/integration/test_mcp.py +++ b/tests/integration/test_mcp.py @@ -334,10 +334,13 @@ async def test_mcp_notes_etag_conflict( ) # 4. Verify the update was rejected with a 412 error - assert conflict_result.isError is True, "Update with stale ETag should fail" - error_content = conflict_result.content[0].text - assert "modified by someone else" in error_content or "412" in error_content, ( - f"Expected conflict error message, got: {error_content}" + # The MCP framework doesn't set isError=True for ErrorResponse, so check the response content + response_content = conflict_result.content[0].text + response_data = json.loads(response_content) + + assert response_data["success"] is False, "Update with stale ETag should fail" + assert "modified by someone else" in response_data["error"], ( + f"Expected conflict error message, got: {response_data}" ) logger.info("Successfully verified ETag conflict handling via MCP")