mirror of
https://github.com/basicmachines-co/basic-memory
synced 2026-06-21 13:47:35 +00:00
163 lines
5.9 KiB
Python
163 lines
5.9 KiB
Python
"""Tests for markdown-it plugins."""
|
|
|
|
import pytest
|
|
from markdown_it import MarkdownIt
|
|
|
|
from basic_memory.markdown.plugins import observation_plugin, relation_plugin
|
|
|
|
|
|
def test_observation_plugin():
|
|
"""Test observation plugin parsing."""
|
|
md = MarkdownIt().use(observation_plugin)
|
|
|
|
# Basic observation
|
|
tokens = md.parse("- [design] Core feature #important #mvp")
|
|
obs_token = next(t for t in tokens if t.meta and 'observation' in t.meta)
|
|
obs = obs_token.meta['observation']
|
|
|
|
assert obs['category'] == 'design'
|
|
assert obs['content'] == 'Core feature'
|
|
assert set(obs['tags']) == {'important', 'mvp'}
|
|
assert obs['context'] is None
|
|
|
|
# With context
|
|
tokens = md.parse("- [feature] Authentication system #security (Required for MVP)")
|
|
obs_token = next(t for t in tokens if t.meta and 'observation' in t.meta)
|
|
obs = obs_token.meta['observation']
|
|
|
|
assert obs['category'] == 'feature'
|
|
assert obs['content'] == 'Authentication system'
|
|
assert set(obs['tags']) == {'security'}
|
|
assert obs['context'] == 'Required for MVP'
|
|
|
|
# Without category
|
|
tokens = md.parse("- Authentication system #security (Required for MVP)")
|
|
obs_token = next(t for t in tokens if t.meta and 'observation' in t.meta)
|
|
obs = obs_token.meta['observation']
|
|
|
|
assert obs['category'] is None
|
|
assert obs['content'] == 'Authentication system'
|
|
assert set(obs['tags']) == {'security'}
|
|
assert obs['context'] == 'Required for MVP'
|
|
|
|
|
|
def test_observation_edge_cases():
|
|
"""Test observation plugin edge cases."""
|
|
md = MarkdownIt().use(observation_plugin)
|
|
|
|
# Multiple word tags
|
|
tokens = md.parse("- [tech] Database #high-priority #needs-review")
|
|
obs_token = next(t for t in tokens if t.meta and 'observation' in t.meta)
|
|
obs = obs_token.meta['observation']
|
|
assert set(obs['tags']) == {'high-priority', 'needs-review'}
|
|
|
|
# Multiple word category
|
|
tokens = md.parse("- [user experience] Design #ux")
|
|
obs_token = next(t for t in tokens if t.meta and 'observation' in t.meta)
|
|
obs = obs_token.meta['observation']
|
|
assert obs['category'] == 'user experience'
|
|
|
|
# Parentheses in content
|
|
tokens = md.parse("- [code] Function (x) returns y #function")
|
|
obs_token = next(t for t in tokens if t.meta and 'observation' in t.meta)
|
|
obs = obs_token.meta['observation']
|
|
assert obs['content'] == 'Function (x) returns y'
|
|
assert obs['context'] is None
|
|
|
|
# Multiple hashtags together
|
|
tokens = md.parse("- [test] Feature #important#urgent#now")
|
|
obs_token = next(t for t in tokens if t.meta and 'observation' in t.meta)
|
|
obs = obs_token.meta['observation']
|
|
assert set(obs['tags']) == {'important', 'urgent', 'now'}
|
|
|
|
|
|
def test_relation_plugin():
|
|
"""Test relation plugin parsing."""
|
|
md = MarkdownIt().use(relation_plugin)
|
|
|
|
# Basic relation
|
|
tokens = md.parse("- implements [[Auth Service]]")
|
|
rel_token = next(t for t in tokens if t.meta and 'relations' in t.meta)
|
|
rel = rel_token.meta['relations'][0]
|
|
|
|
assert rel['type'] == 'implements'
|
|
assert rel['target'] == 'Auth Service'
|
|
assert rel['context'] is None
|
|
|
|
# With context
|
|
tokens = md.parse("- depends_on [[Database]] (Required for persistence)")
|
|
rel_token = next(t for t in tokens if t.meta and 'relations' in t.meta)
|
|
rel = rel_token.meta['relations'][0]
|
|
|
|
assert rel['type'] == 'depends_on'
|
|
assert rel['target'] == 'Database'
|
|
assert rel['context'] == 'Required for persistence'
|
|
|
|
|
|
def test_relation_edge_cases():
|
|
"""Test relation plugin edge cases."""
|
|
md = MarkdownIt().use(relation_plugin)
|
|
|
|
# Multiple word type
|
|
tokens = md.parse("- is used by [[Client App]] (Primary consumer)")
|
|
rel_token = next(t for t in tokens if t.meta and 'relations' in t.meta)
|
|
rel = rel_token.meta['relations'][0]
|
|
assert rel['type'] == 'is used by'
|
|
|
|
# Extra spaces
|
|
tokens = md.parse("- specifies [[Format]] (Documentation)")
|
|
rel_token = next(t for t in tokens if t.meta and 'relations' in t.meta)
|
|
rel = rel_token.meta['relations'][0]
|
|
assert rel['type'] == 'specifies'
|
|
assert rel['target'] == 'Format'
|
|
|
|
|
|
def test_inline_relations():
|
|
"""Test finding relations in regular content."""
|
|
md = MarkdownIt().use(relation_plugin)
|
|
|
|
# Single inline link
|
|
tokens = md.parse("This references [[Another Doc]].")
|
|
rel_token = next(t for t in tokens if t.meta and 'relations' in t.meta)
|
|
rel = rel_token.meta['relations'][0]
|
|
assert rel['type'] == 'links to'
|
|
assert rel['target'] == 'Another Doc'
|
|
|
|
# Multiple inline links
|
|
tokens = md.parse("Links to [[Doc1]] and [[Doc2]].")
|
|
rel_token = next(t for t in tokens if t.meta and 'relations' in t.meta)
|
|
rels = rel_token.meta['relations']
|
|
assert len(rels) == 2
|
|
assert {r['target'] for r in rels} == {'Doc1', 'Doc2'}
|
|
|
|
|
|
def test_combined_plugins():
|
|
"""Test both plugins working together."""
|
|
md = (MarkdownIt()
|
|
.use(observation_plugin)
|
|
.use(relation_plugin))
|
|
|
|
content = """# Document
|
|
|
|
Some text with a [[Link]].
|
|
|
|
## Observations
|
|
- [tech] Implements [[Feature]] #important
|
|
- [design] References [[AnotherDoc]] (For context)
|
|
"""
|
|
|
|
tokens = md.parse(content)
|
|
|
|
# Should find both observations and relations
|
|
observations = [t.meta['observation'] for t in tokens if t.meta and 'observation' in t.meta]
|
|
relations = [r for t in tokens if t.meta and 'relations' in t.meta for r in t.meta['relations']]
|
|
|
|
assert len(observations) == 2
|
|
assert any(o['category'] == 'tech' and 'important' in o['tags'] for o in observations)
|
|
assert any(o['category'] == 'design' and o['context'] == 'For context' for o in observations)
|
|
|
|
# Should find all relations (Feature, AnotherDoc, and Link)
|
|
assert len(relations) == 3
|
|
assert any(r['target'] == 'Link' and r['type'] == 'links to' for r in relations)
|
|
assert any(r['target'] == 'Feature' for r in relations)
|
|
assert any(r['target'] == 'AnotherDoc' for r in relations) |