Skip to main content
Glama

Notion API MCP Server

""" Tests for Notion block formatting and specialized block types. Tests rich text formatting, lists, and todo blocks. """ import pytest import pytest_asyncio from unittest.mock import AsyncMock, MagicMock import httpx import structlog from notion_api_mcp.api.blocks import BlocksAPI # Import common fixtures from ..common.conftest import ( full_access_client, readonly_client, strip_hyphens, ) logger = structlog.get_logger() # Test data constants RICH_TEXT_BLOCKS = { "paragraph": "Basic paragraph text", "heading_1": "Main heading", "heading_2": "Sub heading", "heading_3": "Sub-sub heading", } TEXT_ANNOTATIONS = { "bold": True, "italic": True, "strikethrough": False, "underline": False, "code": False, "color": "blue" } @pytest_asyncio.fixture async def mock_client(): """Mock httpx client for testing.""" client = AsyncMock(spec=httpx.AsyncClient) # Create a mock response mock_response = MagicMock(spec=httpx.Response) mock_response.status_code = 200 mock_response.raise_for_status = MagicMock() mock_response.json = MagicMock(return_value={"object": "block"}) # Make client methods return the mock response client.post.return_value = mock_response client.patch.return_value = mock_response client.get.return_value = mock_response return client @pytest_asyncio.fixture async def blocks_api(mock_client): """BlocksAPI instance with mocked client.""" return BlocksAPI(mock_client) class TestRichTextBlocks: """Test rich text block creation and formatting.""" def test_create_basic_paragraph(self, blocks_api): """Test creating a basic paragraph block.""" block = blocks_api.create_rich_text_block("Test paragraph") assert "paragraph" in block assert block["paragraph"]["rich_text"][0]["text"]["content"] == "Test paragraph" assert block["paragraph"]["rich_text"][0]["type"] == "text" def test_create_heading_blocks(self, blocks_api): """Test creating different heading blocks.""" for block_type, content in RICH_TEXT_BLOCKS.items(): block = blocks_api.create_rich_text_block(content, block_type=block_type) assert block_type in block assert block[block_type]["rich_text"][0]["text"]["content"] == content def test_create_formatted_text(self, blocks_api): """Test creating text with formatting annotations.""" block = blocks_api.create_rich_text_block( "Formatted text", annotations=TEXT_ANNOTATIONS ) rich_text = block["paragraph"]["rich_text"][0] assert rich_text["annotations"]["bold"] is True assert rich_text["annotations"]["italic"] is True assert rich_text["annotations"]["color"] == "blue" def test_create_linked_text(self, blocks_api): """Test creating text with a link.""" block = blocks_api.create_rich_text_block( "Link text", link="https://example.com" ) rich_text = block["paragraph"]["rich_text"][0] assert rich_text["text"]["link"]["url"] == "https://example.com" class TestListBlocks: """Test list block creation and formatting.""" def test_create_basic_list(self, blocks_api): """Test creating a basic bulleted list item.""" block = blocks_api.create_bulleted_list_block("List item") assert "bulleted_list_item" in block assert block["bulleted_list_item"]["rich_text"][0]["text"]["content"] == "List item" def test_create_formatted_list(self, blocks_api): """Test creating a formatted list item.""" block = blocks_api.create_bulleted_list_block( "Formatted item", annotations=TEXT_ANNOTATIONS ) rich_text = block["bulleted_list_item"]["rich_text"][0] assert rich_text["annotations"]["bold"] is True assert rich_text["annotations"]["italic"] is True assert rich_text["annotations"]["color"] == "blue" @pytest.mark.asyncio async def test_nested_list(self, blocks_api): """Test creating nested list items.""" parent = blocks_api.create_bulleted_list_block("Parent item") child = blocks_api.create_bulleted_list_block("Child item") result = await blocks_api.append_children( "test-block-id", [parent, child] ) assert result == {"object": "block"} blocks_api._client.patch.assert_called_once_with( "blocks/test-block-id/children", json={"children": [parent, child]} ) class TestTodoBlocks: """Test todo block creation and formatting.""" def test_create_basic_todo(self, blocks_api): """Test creating a basic todo block.""" block = blocks_api.create_todo_block("Todo item") assert "to_do" in block assert block["to_do"]["rich_text"][0]["text"]["content"] == "Todo item" assert block["to_do"]["checked"] is False def test_create_checked_todo(self, blocks_api): """Test creating a completed todo block.""" block = blocks_api.create_todo_block("Done item", checked=True) assert block["to_do"]["checked"] is True def test_create_formatted_todo(self, blocks_api): """Test creating a formatted todo block.""" block = blocks_api.create_todo_block( "Important todo", annotations=TEXT_ANNOTATIONS ) rich_text = block["to_do"]["rich_text"][0] assert rich_text["annotations"]["bold"] is True assert rich_text["annotations"]["italic"] is True assert rich_text["annotations"]["color"] == "blue" @pytest.mark.asyncio class TestErrorHandling: """Test error handling in block formatting operations.""" async def test_invalid_block_type(self, blocks_api): """Test error handling with invalid block type.""" block = blocks_api.create_rich_text_block( "Test", block_type="invalid_type" ) blocks_api._client.patch.side_effect = httpx.HTTPError("Invalid block type") with pytest.raises(httpx.HTTPError): await blocks_api.append_children("test-id", [block]) async def test_invalid_annotations(self, blocks_api): """Test error handling with invalid annotations.""" block = blocks_api.create_rich_text_block( "Test", annotations={"invalid": "annotation"} ) blocks_api._client.patch.side_effect = httpx.HTTPError("Invalid annotations") with pytest.raises(httpx.HTTPError): await blocks_api.append_children("test-id", [block]) async def test_invalid_color(self, blocks_api): """Test error handling with invalid color.""" block = blocks_api.create_rich_text_block( "Test", annotations={"color": "invalid_color"} ) blocks_api._client.patch.side_effect = httpx.HTTPError("Invalid color") with pytest.raises(httpx.HTTPError): await blocks_api.append_children("test-id", [block])

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/pbohannon/notion-api-mcp'

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