Skip to main content
Glama

Obsidian MCP Server

by bazylhorsey
KnowledgeGraph.test.ts•7.58 kB
import { KnowledgeGraphService } from '../KnowledgeGraph.js'; import type { Note } from '../../types/index.js'; describe('KnowledgeGraphService', () => { let service: KnowledgeGraphService; let testNotes: Note[]; beforeEach(() => { service = new KnowledgeGraphService(); testNotes = [ { path: 'note1.md', title: 'Note 1', content: 'Content with [[note2]] link', tags: ['tag1', 'tag2'], links: [ { source: 'note1.md', target: 'note2', type: 'internal' } ] }, { path: 'note2.md', title: 'Note 2', content: 'Content with [[note3]] link', tags: ['tag2', 'tag3'], links: [ { source: 'note2.md', target: 'note3', type: 'internal' } ] }, { path: 'note3.md', title: 'Note 3', content: 'No links', tags: ['tag3'] }, { path: 'orphan.md', title: 'Orphan', content: 'Isolated note', tags: [] } ]; service.updateNotes(testNotes); }); describe('updateNotes', () => { it('should store notes', () => { const graph = service.buildGraph(); expect(graph.nodes.length).toBeGreaterThan(0); }); }); describe('buildGraph', () => { it('should create nodes for all notes', () => { const graph = service.buildGraph(); const noteNodes = graph.nodes.filter(n => n.type === 'note'); expect(noteNodes).toHaveLength(4); }); it('should create edges for links', () => { const graph = service.buildGraph(); const linkEdges = graph.edges.filter(e => e.type === 'internal'); expect(linkEdges.length).toBeGreaterThan(0); }); it('should create tag nodes', () => { const graph = service.buildGraph(); const tagNodes = graph.nodes.filter(n => n.type === 'tag'); expect(tagNodes.length).toBeGreaterThan(0); }); it('should create folder nodes', () => { const notesWithFolders: Note[] = [ { path: 'folder1/note.md', title: 'Note in Folder', content: 'Content' } ]; service.updateNotes(notesWithFolders); const graph = service.buildGraph(); const folderNodes = graph.nodes.filter(n => n.type === 'folder'); expect(folderNodes.length).toBeGreaterThan(0); }); }); describe('getRelatedNotes', () => { it('should find directly linked notes', () => { const related = service.getRelatedNotes('note1.md', 1); const paths = related.map(n => n.path); expect(paths).toContain('note2.md'); }); it('should find notes at depth 2', () => { const related = service.getRelatedNotes('note1.md', 2); const paths = related.map(n => n.path); expect(paths).toContain('note2.md'); expect(paths).toContain('note3.md'); }); it('should not include the source note', () => { const related = service.getRelatedNotes('note1.md', 2); const paths = related.map(n => n.path); expect(paths).not.toContain('note1.md'); }); it('should return empty for non-existent note', () => { const related = service.getRelatedNotes('nonexistent.md', 2); expect(related).toHaveLength(0); }); it('should respect max depth', () => { const depth1 = service.getRelatedNotes('note1.md', 1); const depth2 = service.getRelatedNotes('note1.md', 2); expect(depth2.length).toBeGreaterThanOrEqual(depth1.length); }); }); describe('findPath', () => { it('should find direct path', () => { const path = service.findPath('note1.md', 'note2.md'); expect(path).not.toBeNull(); expect(path).toContain('note1.md'); expect(path).toContain('note2.md'); }); it('should find indirect path', () => { const path = service.findPath('note1.md', 'note3.md'); expect(path).not.toBeNull(); expect(path).toContain('note1.md'); expect(path).toContain('note3.md'); }); it('should return null for unreachable notes', () => { const path = service.findPath('note1.md', 'orphan.md'); expect(path).toBeNull(); }); it('should return single-item path for same note', () => { const path = service.findPath('note1.md', 'note1.md'); expect(path).toEqual(['note1.md']); }); }); describe('analyzeGraph', () => { it('should count total nodes', () => { const analysis = service.analyzeGraph(); expect(analysis.totalNodes).toBe(4); }); it('should count edges', () => { const analysis = service.analyzeGraph(); expect(analysis.totalEdges).toBeGreaterThan(0); }); it('should identify orphan notes', () => { const analysis = service.analyzeGraph(); expect(analysis.orphanNotes).toContain('orphan.md'); }); it('should find most connected nodes', () => { const analysis = service.analyzeGraph(); expect(analysis.mostConnectedNodes).toBeDefined(); expect(analysis.mostConnectedNodes.length).toBeGreaterThan(0); }); }); describe('getNotesByTag', () => { it('should find notes with specific tag', () => { const notes = service.getNotesByTag('tag2'); expect(notes).toHaveLength(2); }); it('should return empty for non-existent tag', () => { const notes = service.getNotesByTag('nonexistent'); expect(notes).toHaveLength(0); }); }); describe('getNotesByFolder', () => { it('should find notes in folder', () => { const notesWithFolders: Note[] = [ { path: 'folder1/note1.md', title: 'Note 1', content: 'Content' }, { path: 'folder1/note2.md', title: 'Note 2', content: 'Content' }, { path: 'folder2/note3.md', title: 'Note 3', content: 'Content' } ]; service.updateNotes(notesWithFolders); const notes = service.getNotesByFolder('folder1'); expect(notes).toHaveLength(2); }); }); describe('getAllTags', () => { it('should return all tags with counts', () => { const tags = service.getAllTags(); expect(tags.length).toBeGreaterThan(0); expect(tags[0]).toHaveProperty('tag'); expect(tags[0]).toHaveProperty('count'); }); it('should sort by count descending', () => { const tags = service.getAllTags(); if (tags.length > 1) { expect(tags[0].count).toBeGreaterThanOrEqual(tags[1].count); } }); }); describe('suggestRelatedNotes', () => { it('should suggest notes with shared tags', () => { const suggestions = service.suggestRelatedNotes('note1.md', 5); expect(suggestions).toBeDefined(); expect(Array.isArray(suggestions)).toBe(true); }); it('should return limited results', () => { const suggestions = service.suggestRelatedNotes('note1.md', 2); expect(suggestions.length).toBeLessThanOrEqual(2); }); it('should not suggest the note itself', () => { const suggestions = service.suggestRelatedNotes('note1.md', 5); expect(suggestions.map(s => s.path)).not.toContain('note1.md'); }); it('should return empty for non-existent note', () => { const suggestions = service.suggestRelatedNotes('nonexistent.md', 5); expect(suggestions).toHaveLength(0); }); it('should have scores', () => { const suggestions = service.suggestRelatedNotes('note1.md', 5); if (suggestions.length > 0) { expect(suggestions[0]).toHaveProperty('score'); expect(typeof suggestions[0].score).toBe('number'); } }); }); });

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/bazylhorsey/obsidian-mcp-server'

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