mirror of
https://github.com/basicmachines-co/basic-memory
synced 2026-06-21 13:47:35 +00:00
530cbac73f
Signed-off-by: phernandez <paul@basicmachines.co>
290 lines
8.2 KiB
Python
290 lines
8.2 KiB
Python
"""Tests for canvas tool that exercise the full stack with SQLite."""
|
|
|
|
import json
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from basic_memory.mcp.tools import canvas
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_create_canvas(app, project_config, test_project):
|
|
"""Test creating a new canvas file.
|
|
|
|
Should:
|
|
- Create canvas file with correct content
|
|
- Create entity in database
|
|
- Return successful status
|
|
"""
|
|
# Test data
|
|
nodes = [
|
|
{
|
|
"id": "node1",
|
|
"type": "text",
|
|
"text": "Test Node",
|
|
"x": 100,
|
|
"y": 200,
|
|
"width": 400,
|
|
"height": 300,
|
|
}
|
|
]
|
|
edges = [{"id": "edge1", "fromNode": "node1", "toNode": "node2", "label": "connects to"}]
|
|
title = "test-canvas"
|
|
folder = "visualizations"
|
|
|
|
# Execute
|
|
result = await canvas.fn(
|
|
project=test_project.name, nodes=nodes, edges=edges, title=title, directory=folder
|
|
)
|
|
|
|
# Verify result message
|
|
assert result
|
|
assert "Created: visualizations/test-canvas" in result
|
|
assert "The canvas is ready to open in Obsidian" in result
|
|
|
|
# Verify file was created
|
|
file_path = Path(project_config.home) / folder / f"{title}.canvas"
|
|
assert file_path.exists()
|
|
|
|
# Verify content is correct
|
|
content = json.loads(file_path.read_text(encoding="utf-8"))
|
|
assert content["nodes"] == nodes
|
|
assert content["edges"] == edges
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_create_canvas_with_extension(app, project_config, test_project):
|
|
"""Test creating a canvas file with .canvas extension already in the title."""
|
|
# Test data
|
|
nodes = [
|
|
{
|
|
"id": "node1",
|
|
"type": "text",
|
|
"text": "Extension Test",
|
|
"x": 100,
|
|
"y": 200,
|
|
"width": 400,
|
|
"height": 300,
|
|
}
|
|
]
|
|
edges = []
|
|
title = "extension-test.canvas" # Already has extension
|
|
folder = "visualizations"
|
|
|
|
# Execute
|
|
result = await canvas.fn(
|
|
project=test_project.name, nodes=nodes, edges=edges, title=title, directory=folder
|
|
)
|
|
|
|
# Verify
|
|
assert "Created: visualizations/extension-test.canvas" in result
|
|
|
|
# Verify file exists with correct name (shouldn't have double extension)
|
|
file_path = Path(project_config.home) / folder / title
|
|
assert file_path.exists()
|
|
|
|
# Verify content
|
|
content = json.loads(file_path.read_text(encoding="utf-8"))
|
|
assert content["nodes"] == nodes
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_update_existing_canvas(app, project_config, test_project):
|
|
"""Test updating an existing canvas file."""
|
|
# First create a canvas
|
|
nodes = [
|
|
{
|
|
"id": "initial",
|
|
"type": "text",
|
|
"text": "Initial content",
|
|
"x": 0,
|
|
"y": 0,
|
|
"width": 200,
|
|
"height": 100,
|
|
}
|
|
]
|
|
edges = []
|
|
title = "update-test"
|
|
folder = "visualizations"
|
|
|
|
# Create initial canvas
|
|
await canvas.fn(
|
|
project=test_project.name, nodes=nodes, edges=edges, title=title, directory=folder
|
|
)
|
|
|
|
# Verify file exists
|
|
file_path = Path(project_config.home) / folder / f"{title}.canvas"
|
|
assert file_path.exists()
|
|
|
|
# Now update with new content
|
|
updated_nodes = [
|
|
{
|
|
"id": "updated",
|
|
"type": "text",
|
|
"text": "Updated content",
|
|
"x": 100,
|
|
"y": 100,
|
|
"width": 300,
|
|
"height": 200,
|
|
}
|
|
]
|
|
updated_edges = [
|
|
{"id": "new-edge", "fromNode": "updated", "toNode": "other", "label": "new connection"}
|
|
]
|
|
|
|
# Execute update
|
|
result = await canvas.fn(
|
|
project=test_project.name,
|
|
nodes=updated_nodes,
|
|
edges=updated_edges,
|
|
title=title,
|
|
directory=folder,
|
|
)
|
|
|
|
# Verify result indicates update
|
|
assert "Updated: visualizations/update-test.canvas" in result
|
|
|
|
# Verify content was updated
|
|
content = json.loads(file_path.read_text(encoding="utf-8"))
|
|
assert content["nodes"] == updated_nodes
|
|
assert content["edges"] == updated_edges
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_create_canvas_with_nested_folders(app, project_config, test_project):
|
|
"""Test creating a canvas in nested folders that don't exist yet."""
|
|
# Test data
|
|
nodes = [
|
|
{
|
|
"id": "test",
|
|
"type": "text",
|
|
"text": "Nested folder test",
|
|
"x": 0,
|
|
"y": 0,
|
|
"width": 200,
|
|
"height": 100,
|
|
}
|
|
]
|
|
edges = []
|
|
title = "nested-test"
|
|
folder = "visualizations/nested/folders" # Deep path
|
|
|
|
# Execute
|
|
result = await canvas.fn(
|
|
project=test_project.name, nodes=nodes, edges=edges, title=title, directory=folder
|
|
)
|
|
|
|
# Verify
|
|
assert "Created: visualizations/nested/folders/nested-test.canvas" in result
|
|
|
|
# Verify folders and file were created
|
|
file_path = Path(project_config.home) / folder / f"{title}.canvas"
|
|
assert file_path.exists()
|
|
assert file_path.parent.exists()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_create_canvas_complex_content(app, project_config, test_project):
|
|
"""Test creating a canvas with complex content structures."""
|
|
# Test data - more complex structure with all node types
|
|
nodes = [
|
|
{
|
|
"id": "text-node",
|
|
"type": "text",
|
|
"text": "# Heading\n\nThis is a test with *markdown* formatting",
|
|
"x": 100,
|
|
"y": 100,
|
|
"width": 400,
|
|
"height": 300,
|
|
"color": "4", # Using a preset color
|
|
},
|
|
{
|
|
"id": "file-node",
|
|
"type": "file",
|
|
"file": "test/test-file.md", # Reference a file
|
|
"x": 600,
|
|
"y": 100,
|
|
"width": 400,
|
|
"height": 300,
|
|
"color": "#FF5500", # Using hex color
|
|
},
|
|
{
|
|
"id": "link-node",
|
|
"type": "link",
|
|
"url": "https://example.com",
|
|
"x": 100,
|
|
"y": 500,
|
|
"width": 400,
|
|
"height": 200,
|
|
},
|
|
{
|
|
"id": "group-node",
|
|
"type": "group",
|
|
"label": "Group Label",
|
|
"x": 600,
|
|
"y": 500,
|
|
"width": 600,
|
|
"height": 400,
|
|
},
|
|
]
|
|
|
|
edges = [
|
|
{
|
|
"id": "edge1",
|
|
"fromNode": "text-node",
|
|
"toNode": "file-node",
|
|
"label": "references",
|
|
"fromSide": "right",
|
|
"toSide": "left",
|
|
},
|
|
{
|
|
"id": "edge2",
|
|
"fromNode": "link-node",
|
|
"toNode": "group-node",
|
|
"label": "belongs to",
|
|
"color": "6",
|
|
},
|
|
]
|
|
|
|
title = "complex-test"
|
|
folder = "visualizations"
|
|
|
|
# Create a test file that we're referencing
|
|
test_file_path = Path(project_config.home) / "test/test-file.md"
|
|
test_file_path.parent.mkdir(parents=True, exist_ok=True)
|
|
test_file_path.write_text("# Test File\nThis is referenced by the canvas")
|
|
|
|
# Execute
|
|
result = await canvas.fn(
|
|
project=test_project.name, nodes=nodes, edges=edges, title=title, directory=folder
|
|
)
|
|
|
|
# Verify
|
|
assert "Created: visualizations/complex-test.canvas" in result
|
|
|
|
# Verify file was created
|
|
file_path = Path(project_config.home) / folder / f"{title}.canvas"
|
|
assert file_path.exists()
|
|
|
|
# Verify content is correct with all complex structures
|
|
content = json.loads(file_path.read_text(encoding="utf-8"))
|
|
assert len(content["nodes"]) == 4
|
|
assert len(content["edges"]) == 2
|
|
|
|
# Verify specific content elements are preserved
|
|
assert any(node["type"] == "text" and "#" in node["text"] for node in content["nodes"])
|
|
assert any(
|
|
node["type"] == "file" and "test-file.md" in node["file"] for node in content["nodes"]
|
|
)
|
|
assert any(node["type"] == "link" and "example.com" in node["url"] for node in content["nodes"])
|
|
assert any(
|
|
node["type"] == "group" and "Group Label" == node["label"] for node in content["nodes"]
|
|
)
|
|
|
|
# Verify edge properties
|
|
assert any(
|
|
edge["fromSide"] == "right" and edge["toSide"] == "left" for edge in content["edges"]
|
|
)
|
|
assert any(edge["label"] == "belongs to" and edge["color"] == "6" for edge in content["edges"])
|