Files
obsidian-mcp-server/tests/__mocks__/adapters.ts
Bill 2e30b81f01 test: comprehensive coverage for NoteTools
Add extensive test suite for note-tools.ts covering all major operations
and error paths. Improves statement coverage from 13.94% to 96.01%.

Tests added:
- readNote: success, errors, frontmatter parsing
- createNote: success, conflict strategies (error/overwrite/rename), parent folder creation
- updateNote: success, errors, waypoint protection
- deleteNote: soft/permanent delete, dry run, version checking
- renameFile: success, errors, version checking, parent folder creation
- readExcalidraw: success, non-Excalidraw files, errors
- updateFrontmatter: success, field removal, version checking
- updateSections: success, invalid ranges, version checking
- Path validation for all methods
- Empty path validation for all methods

Mock enhancements:
- Added modify, delete, trash methods to VaultAdapter mock
- Added parseYaml function to Obsidian mock for frontmatter testing

Coverage improvements for note-tools.ts:
- Statements: 13.94% -> 96.01% (+82.07%)
- Branches: 5.1% -> 88.44% (+83.34%)
- Functions: 27.27% -> 90.9% (+63.63%)
- Lines: 13.94% -> 96.4% (+82.46%)
2025-10-20 00:13:03 -04:00

80 lines
2.1 KiB
TypeScript

import { IVaultAdapter, IMetadataCacheAdapter, IFileManagerAdapter } from '../../src/adapters/interfaces';
import { TFile, TFolder, TAbstractFile, CachedMetadata } from 'obsidian';
/**
* Create a mock VaultAdapter with jest.fn() for all methods
*/
export function createMockVaultAdapter(overrides?: Partial<IVaultAdapter>): IVaultAdapter {
return {
read: jest.fn(),
stat: jest.fn(),
getAbstractFileByPath: jest.fn(),
getMarkdownFiles: jest.fn(),
getRoot: jest.fn(),
process: jest.fn(),
createFolder: jest.fn(),
create: jest.fn(),
modify: jest.fn(),
delete: jest.fn(),
trash: jest.fn(),
...overrides
};
}
/**
* Create a mock MetadataCacheAdapter with jest.fn() for all methods
*/
export function createMockMetadataCacheAdapter(overrides?: Partial<IMetadataCacheAdapter>): IMetadataCacheAdapter {
return {
getFileCache: jest.fn(),
getFirstLinkpathDest: jest.fn(),
resolvedLinks: {},
unresolvedLinks: {},
...overrides
};
}
/**
* Create a mock FileManagerAdapter with jest.fn() for all methods
*/
export function createMockFileManagerAdapter(overrides?: Partial<IFileManagerAdapter>): IFileManagerAdapter {
return {
renameFile: jest.fn(),
trashFile: jest.fn(),
processFrontMatter: jest.fn(),
...overrides
};
}
/**
* Helper to create a mock TFile with proper prototype chain
*/
export function createMockTFile(path: string, stat?: { ctime: number; mtime: number; size: number }): TFile {
const file = Object.create(TFile.prototype);
Object.assign(file, {
path,
basename: path.split('/').pop()?.replace('.md', '') || '',
extension: 'md',
name: path.split('/').pop() || '',
stat: stat || { ctime: Date.now(), mtime: Date.now(), size: 100 },
vault: {} as any,
parent: null
});
return file;
}
/**
* Helper to create a mock TFolder with proper prototype chain
*/
export function createMockTFolder(path: string, children?: TAbstractFile[]): TFolder {
const folder = Object.create(TFolder.prototype);
Object.assign(folder, {
path,
name: path.split('/').pop() || '',
children: children || [],
vault: {} as any,
parent: null,
isRoot: function() { return path === '' || path === '/'; }
});
return folder;
}