Skip to main content
Glama

basic-memory

test_entity_parser.py8.67 kB
"""Tests for entity markdown parsing.""" from datetime import datetime from pathlib import Path from textwrap import dedent import pytest from basic_memory.markdown.schemas import EntityMarkdown, EntityFrontmatter, Relation from basic_memory.markdown.entity_parser import parse @pytest.fixture def valid_entity_content(): """A complete, valid entity file with all features.""" return dedent(""" --- title: Auth Service type: component permalink: auth_service created: 2024-12-21T14:00:00Z modified: 2024-12-21T14:00:00Z tags: authentication, security, core --- Core authentication service that handles user authentication. some [[Random Link]] another [[Random Link with Title|Titled Link]] ## Observations - [design] Stateless authentication #security #architecture (JWT based) - [feature] Mobile client support #mobile #oauth (Required for App Store) - [tech] Caching layer #performance (Redis implementation) ## Relations - implements [[OAuth Implementation]] (Core auth flows) - uses [[Redis Cache]] (Token caching) - specified_by [[Auth API Spec]] (OpenAPI spec) """) @pytest.mark.asyncio async def test_parse_complete_file(project_config, entity_parser, valid_entity_content): """Test parsing a complete entity file with all features.""" test_file = project_config.home / "test_entity.md" test_file.write_text(valid_entity_content) entity = await entity_parser.parse_file(test_file) # Verify entity structure assert isinstance(entity, EntityMarkdown) assert isinstance(entity.frontmatter, EntityFrontmatter) assert isinstance(entity.content, str) # Check frontmatter assert entity.frontmatter.title == "Auth Service" assert entity.frontmatter.type == "component" assert entity.frontmatter.permalink == "auth_service" assert set(entity.frontmatter.tags) == {"authentication", "security", "core"} # Check content assert "Core authentication service that handles user authentication." in entity.content # Check observations assert len(entity.observations) == 3 obs = entity.observations[0] assert obs.category == "design" assert obs.content == "Stateless authentication #security #architecture" assert set(obs.tags or []) == {"security", "architecture"} assert obs.context == "JWT based" # Check relations assert len(entity.relations) == 5 assert ( Relation(type="implements", target="OAuth Implementation", context="Core auth flows") in entity.relations ), "missing [[OAuth Implementation]]" assert ( Relation(type="uses", target="Redis Cache", context="Token caching") in entity.relations ), "missing [[Redis Cache]]" assert ( Relation(type="specified_by", target="Auth API Spec", context="OpenAPI spec") in entity.relations ), "missing [[Auth API Spec]]" # inline links in content assert Relation(type="links to", target="Random Link", context=None) in entity.relations, ( "missing [[Random Link]]" ) assert ( Relation(type="links to", target="Random Link with Title|Titled Link", context=None) in entity.relations ), "missing [[Random Link with Title|Titled Link]]" @pytest.mark.asyncio async def test_parse_minimal_file(project_config, entity_parser): """Test parsing a minimal valid entity file.""" content = dedent(""" --- type: component tags: [] --- # Minimal Entity ## Observations - [note] Basic observation #test ## Relations - references [[Other Entity]] """) test_file = project_config.home / "minimal.md" test_file.write_text(content) entity = await entity_parser.parse_file(test_file) assert entity.frontmatter.type == "component" assert entity.frontmatter.permalink is None assert len(entity.observations) == 1 assert len(entity.relations) == 1 assert entity.created is not None assert entity.modified is not None @pytest.mark.asyncio async def test_error_handling(project_config, entity_parser): """Test error handling.""" # Missing file with pytest.raises(FileNotFoundError): await entity_parser.parse_file(Path("nonexistent.md")) # Invalid file encoding test_file = project_config.home / "binary.md" with open(test_file, "wb") as f: f.write(b"\x80\x81") # Invalid UTF-8 with pytest.raises(UnicodeDecodeError): await entity_parser.parse_file(test_file) @pytest.mark.asyncio async def test_parse_file_without_section_headers(project_config, entity_parser): """Test parsing a minimal valid entity file.""" content = dedent(""" --- type: component permalink: minimal_entity status: draft tags: [] --- # Minimal Entity some text some [[Random Link]] - [note] Basic observation #test - references [[Other Entity]] """) test_file = project_config.home / "minimal.md" test_file.write_text(content) entity = await entity_parser.parse_file(test_file) assert entity.frontmatter.type == "component" assert entity.frontmatter.permalink == "minimal_entity" assert "some text\nsome [[Random Link]]" in entity.content assert len(entity.observations) == 1 assert entity.observations[0].category == "note" assert entity.observations[0].content == "Basic observation #test" assert entity.observations[0].tags == ["test"] assert len(entity.relations) == 2 assert entity.relations[0].type == "links to" assert entity.relations[0].target == "Random Link" assert entity.relations[1].type == "references" assert entity.relations[1].target == "Other Entity" def test_parse_date_formats(entity_parser): """Test date parsing functionality.""" # Valid formats assert entity_parser.parse_date("2024-01-15") is not None assert entity_parser.parse_date("Jan 15, 2024") is not None assert entity_parser.parse_date("2024-01-15 10:00 AM") is not None assert entity_parser.parse_date(datetime.now()) is not None # Invalid formats assert entity_parser.parse_date(None) is None assert entity_parser.parse_date(123) is None # Non-string/datetime assert entity_parser.parse_date("not a date") is None # Unparseable string assert entity_parser.parse_date("") is None # Empty string # Test dateparser error handling assert entity_parser.parse_date("25:00:00") is None # Invalid time def test_parse_empty_content(): """Test parsing empty or minimal content.""" result = parse("") assert result.content == "" assert len(result.observations) == 0 assert len(result.relations) == 0 result = parse("# Just a title") assert result.content == "# Just a title" assert len(result.observations) == 0 assert len(result.relations) == 0 @pytest.mark.asyncio async def test_parse_file_with_absolute_path(project_config, entity_parser): """Test parsing a file with an absolute path.""" content = dedent(""" --- type: component permalink: absolute_path_test --- # Absolute Path Test A file with an absolute path. """) # Create a test file in the project directory test_file = project_config.home / "absolute_path_test.md" test_file.write_text(content) # Get the absolute path to the test file absolute_path = test_file.resolve() # Parse the file using the absolute path entity = await entity_parser.parse_file(absolute_path) # Verify the file was parsed correctly assert entity.frontmatter.permalink == "absolute_path_test" assert "Absolute Path Test" in entity.content assert entity.created is not None assert entity.modified is not None # @pytest.mark.asyncio # async def test_parse_file_invalid_yaml(test_config, entity_parser): # """Test parsing file with invalid YAML frontmatter.""" # content = dedent(""" # --- # invalid: [yaml: ]syntax] # --- # # # Invalid YAML Frontmatter # """) # # test_file = test_config.home / "invalid_yaml.md" # test_file.write_text(content) # # # Should handle invalid YAML gracefully # entity = await entity_parser.parse_file(test_file) # assert entity.frontmatter.title == "invalid_yaml.md" # assert entity.frontmatter.type == "note" # assert entity.content.strip() == "# Invalid YAML Frontmatter"

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/basicmachines-co/basic-memory'

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