test: add comprehensive VaultTools coverage tests
Added extensive test coverage for VaultTools to increase coverage from 54.9% to 93.83%: getVaultInfo tests: - Return vault info with total notes and size - Handle empty vault - Handle files with missing stat info - Handle errors gracefully - Format large file sizes correctly (KB, MB, GB) search tests: - Search for literal text - Search with regex pattern - Handle invalid regex pattern - Filter by folder - Respect maxResults limit - Handle file read errors gracefully - Handle case sensitive search - Extract snippets correctly - Handle zero-width regex matches - Handle general search errors Waypoint tests (searchWaypoints, getFolderWaypoint, isFolderNote): - Search for waypoints in vault - Filter waypoints by folder - Extract waypoint from file - Detect folder notes - Handle file not found errors - Handle general errors resolveWikilink tests: - Resolve wikilink successfully - Provide suggestions for unresolved links - Handle errors gracefully - Handle invalid source path getBacklinks unlinked mentions tests: - Find unlinked mentions - Skip files that already have linked backlinks - Skip target file itself in unlinked mentions - Not return unlinked mentions when includeUnlinked is false list edge case tests: - Handle invalid path - Handle non-existent folder - Handle path pointing to file instead of folder - Handle cursor not found in pagination validateWikilinks edge case tests: - Handle invalid path
This commit is contained in:
@@ -577,5 +577,532 @@ describe('VaultTools', () => {
|
||||
expect(parsed.resolvedLinks.length).toBe(1);
|
||||
expect(parsed.unresolvedLinks.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should handle invalid path', async () => {
|
||||
mockVault.getAbstractFileByPath = jest.fn().mockReturnValue(null);
|
||||
|
||||
const result = await vaultTools.validateWikilinks('../invalid');
|
||||
|
||||
expect(result.isError).toBe(true);
|
||||
expect(result.content[0].text).toContain('not found');
|
||||
});
|
||||
});
|
||||
|
||||
describe('resolveWikilink', () => {
|
||||
it('should return error if source file not found', async () => {
|
||||
mockVault.getAbstractFileByPath = jest.fn().mockReturnValue(null);
|
||||
|
||||
const result = await vaultTools.resolveWikilink('nonexistent.md', 'target');
|
||||
|
||||
expect(result.isError).toBe(true);
|
||||
expect(result.content[0].text).toContain('not found');
|
||||
});
|
||||
|
||||
it('should resolve wikilink successfully', async () => {
|
||||
const sourceFile = createMockTFile('source.md');
|
||||
const targetFile = createMockTFile('target.md');
|
||||
|
||||
mockVault.getAbstractFileByPath = jest.fn().mockReturnValue(sourceFile);
|
||||
mockMetadata.getFirstLinkpathDest = jest.fn().mockReturnValue(targetFile);
|
||||
|
||||
const result = await vaultTools.resolveWikilink('source.md', 'target');
|
||||
|
||||
expect(result.isError).toBeUndefined();
|
||||
const parsed = JSON.parse(result.content[0].text);
|
||||
expect(parsed.resolved).toBe(true);
|
||||
expect(parsed.targetPath).toBe('target.md');
|
||||
expect(parsed.suggestions).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should provide suggestions for unresolved links', async () => {
|
||||
const sourceFile = createMockTFile('source.md');
|
||||
const similarFile = createMockTFile('target-similar.md');
|
||||
|
||||
mockVault.getAbstractFileByPath = jest.fn().mockReturnValue(sourceFile);
|
||||
mockMetadata.getFirstLinkpathDest = jest.fn().mockReturnValue(null);
|
||||
mockVault.getMarkdownFiles = jest.fn().mockReturnValue([similarFile]);
|
||||
|
||||
const result = await vaultTools.resolveWikilink('source.md', 'target');
|
||||
|
||||
expect(result.isError).toBeUndefined();
|
||||
const parsed = JSON.parse(result.content[0].text);
|
||||
expect(parsed.resolved).toBe(false);
|
||||
expect(parsed.suggestions).toBeDefined();
|
||||
expect(Array.isArray(parsed.suggestions)).toBe(true);
|
||||
});
|
||||
|
||||
it('should handle errors gracefully', async () => {
|
||||
const sourceFile = createMockTFile('source.md');
|
||||
|
||||
mockVault.getAbstractFileByPath = jest.fn().mockReturnValue(sourceFile);
|
||||
mockMetadata.getFirstLinkpathDest = jest.fn().mockImplementation(() => {
|
||||
throw new Error('Cache error');
|
||||
});
|
||||
|
||||
const result = await vaultTools.resolveWikilink('source.md', 'target');
|
||||
|
||||
expect(result.isError).toBe(true);
|
||||
expect(result.content[0].text).toContain('error');
|
||||
});
|
||||
|
||||
it('should handle invalid source path', async () => {
|
||||
mockVault.getAbstractFileByPath = jest.fn().mockReturnValue(null);
|
||||
|
||||
const result = await vaultTools.resolveWikilink('../invalid', 'target');
|
||||
|
||||
expect(result.isError).toBe(true);
|
||||
expect(result.content[0].text).toContain('not found');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getVaultInfo', () => {
|
||||
it('should return vault info with total notes and size', async () => {
|
||||
const mockFiles = [
|
||||
createMockTFile('note1.md', { size: 100, ctime: 1000, mtime: 2000 }),
|
||||
createMockTFile('note2.md', { size: 200, ctime: 1000, mtime: 2000 })
|
||||
];
|
||||
|
||||
mockVault.getMarkdownFiles = jest.fn().mockReturnValue(mockFiles);
|
||||
mockVault.stat = jest.fn()
|
||||
.mockReturnValueOnce({ size: 100, ctime: 1000, mtime: 2000 })
|
||||
.mockReturnValueOnce({ size: 200, ctime: 1000, mtime: 2000 });
|
||||
|
||||
const result = await vaultTools.getVaultInfo();
|
||||
|
||||
expect(result.isError).toBeUndefined();
|
||||
const parsed = JSON.parse(result.content[0].text);
|
||||
expect(parsed.totalNotes).toBe(2);
|
||||
expect(parsed.totalSize).toBe(300);
|
||||
expect(parsed.sizeFormatted).toBe('300 Bytes');
|
||||
});
|
||||
|
||||
it('should handle empty vault', async () => {
|
||||
mockVault.getMarkdownFiles = jest.fn().mockReturnValue([]);
|
||||
|
||||
const result = await vaultTools.getVaultInfo();
|
||||
|
||||
expect(result.isError).toBeUndefined();
|
||||
const parsed = JSON.parse(result.content[0].text);
|
||||
expect(parsed.totalNotes).toBe(0);
|
||||
expect(parsed.totalSize).toBe(0);
|
||||
expect(parsed.sizeFormatted).toBe('0 Bytes');
|
||||
});
|
||||
|
||||
it('should handle files with missing stat info', async () => {
|
||||
const mockFiles = [
|
||||
createMockTFile('note1.md'),
|
||||
createMockTFile('note2.md')
|
||||
];
|
||||
|
||||
mockVault.getMarkdownFiles = jest.fn().mockReturnValue(mockFiles);
|
||||
mockVault.stat = jest.fn()
|
||||
.mockReturnValueOnce(null)
|
||||
.mockReturnValueOnce({ size: 100, ctime: 1000, mtime: 2000 });
|
||||
|
||||
const result = await vaultTools.getVaultInfo();
|
||||
|
||||
expect(result.isError).toBeUndefined();
|
||||
const parsed = JSON.parse(result.content[0].text);
|
||||
expect(parsed.totalNotes).toBe(2);
|
||||
expect(parsed.totalSize).toBe(100); // Only counts the file with valid stat
|
||||
});
|
||||
|
||||
it('should handle errors gracefully', async () => {
|
||||
mockVault.getMarkdownFiles = jest.fn().mockImplementation(() => {
|
||||
throw new Error('Vault access error');
|
||||
});
|
||||
|
||||
const result = await vaultTools.getVaultInfo();
|
||||
|
||||
expect(result.isError).toBe(true);
|
||||
expect(result.content[0].text).toContain('Get vault info error');
|
||||
});
|
||||
|
||||
it('should format large file sizes correctly', async () => {
|
||||
const mockFiles = [
|
||||
createMockTFile('large.md', { size: 1024 * 1024 * 5, ctime: 1000, mtime: 2000 })
|
||||
];
|
||||
|
||||
mockVault.getMarkdownFiles = jest.fn().mockReturnValue(mockFiles);
|
||||
mockVault.stat = jest.fn().mockReturnValue({ size: 1024 * 1024 * 5, ctime: 1000, mtime: 2000 });
|
||||
|
||||
const result = await vaultTools.getVaultInfo();
|
||||
|
||||
expect(result.isError).toBeUndefined();
|
||||
const parsed = JSON.parse(result.content[0].text);
|
||||
expect(parsed.sizeFormatted).toContain('MB');
|
||||
});
|
||||
});
|
||||
|
||||
describe('search', () => {
|
||||
it('should search for literal text', async () => {
|
||||
const mockFile = createMockTFile('test.md');
|
||||
mockVault.getMarkdownFiles = jest.fn().mockReturnValue([mockFile]);
|
||||
mockVault.read = jest.fn().mockResolvedValue('Hello world\nThis is a test');
|
||||
|
||||
const result = await vaultTools.search({ query: 'test' });
|
||||
|
||||
expect(result.isError).toBeUndefined();
|
||||
const parsed = JSON.parse(result.content[0].text);
|
||||
expect(parsed.totalMatches).toBeGreaterThan(0);
|
||||
expect(parsed.matches[0].path).toBe('test.md');
|
||||
});
|
||||
|
||||
it('should search with regex pattern', async () => {
|
||||
const mockFile = createMockTFile('test.md');
|
||||
mockVault.getMarkdownFiles = jest.fn().mockReturnValue([mockFile]);
|
||||
mockVault.read = jest.fn().mockResolvedValue('test123\ntest456');
|
||||
|
||||
const result = await vaultTools.search({ query: 'test\\d+', isRegex: true });
|
||||
|
||||
expect(result.isError).toBeUndefined();
|
||||
const parsed = JSON.parse(result.content[0].text);
|
||||
expect(parsed.isRegex).toBe(true);
|
||||
expect(parsed.totalMatches).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('should handle invalid regex pattern', async () => {
|
||||
const result = await vaultTools.search({ query: '[invalid(regex', isRegex: true });
|
||||
|
||||
expect(result.isError).toBe(true);
|
||||
expect(result.content[0].text).toContain('Invalid regex pattern');
|
||||
});
|
||||
|
||||
it('should filter by folder', async () => {
|
||||
const mockFile1 = createMockTFile('folder/test.md');
|
||||
const mockFile2 = createMockTFile('other/test.md');
|
||||
mockVault.getMarkdownFiles = jest.fn().mockReturnValue([mockFile1, mockFile2]);
|
||||
mockVault.read = jest.fn().mockResolvedValue('test content');
|
||||
|
||||
const result = await vaultTools.search({ query: 'test', folder: 'folder' });
|
||||
|
||||
expect(result.isError).toBeUndefined();
|
||||
const parsed = JSON.parse(result.content[0].text);
|
||||
expect(parsed.filesSearched).toBe(1);
|
||||
});
|
||||
|
||||
it('should respect maxResults limit', async () => {
|
||||
const mockFile = createMockTFile('test.md');
|
||||
mockVault.getMarkdownFiles = jest.fn().mockReturnValue([mockFile]);
|
||||
mockVault.read = jest.fn().mockResolvedValue('test test test test test');
|
||||
|
||||
const result = await vaultTools.search({ query: 'test', maxResults: 2 });
|
||||
|
||||
expect(result.isError).toBeUndefined();
|
||||
const parsed = JSON.parse(result.content[0].text);
|
||||
expect(parsed.totalMatches).toBeLessThanOrEqual(2);
|
||||
});
|
||||
|
||||
it('should handle file read errors gracefully', async () => {
|
||||
const mockFile = createMockTFile('test.md');
|
||||
mockVault.getMarkdownFiles = jest.fn().mockReturnValue([mockFile]);
|
||||
mockVault.read = jest.fn().mockRejectedValue(new Error('Read error'));
|
||||
|
||||
const result = await vaultTools.search({ query: 'test' });
|
||||
|
||||
// Should not throw, just skip the file
|
||||
expect(result.isError).toBeUndefined();
|
||||
const parsed = JSON.parse(result.content[0].text);
|
||||
expect(parsed.totalMatches).toBe(0);
|
||||
});
|
||||
|
||||
it('should handle case sensitive search', async () => {
|
||||
const mockFile = createMockTFile('test.md');
|
||||
mockVault.getMarkdownFiles = jest.fn().mockReturnValue([mockFile]);
|
||||
mockVault.read = jest.fn().mockResolvedValue('Test test TEST');
|
||||
|
||||
const result = await vaultTools.search({ query: 'test', caseSensitive: true });
|
||||
|
||||
expect(result.isError).toBeUndefined();
|
||||
const parsed = JSON.parse(result.content[0].text);
|
||||
// Should only match lowercase 'test'
|
||||
expect(parsed.totalMatches).toBe(1);
|
||||
});
|
||||
|
||||
it('should extract snippets correctly', async () => {
|
||||
const mockFile = createMockTFile('test.md');
|
||||
const longLine = 'a'.repeat(200) + 'target' + 'b'.repeat(200);
|
||||
mockVault.getMarkdownFiles = jest.fn().mockReturnValue([mockFile]);
|
||||
mockVault.read = jest.fn().mockResolvedValue(longLine);
|
||||
|
||||
const result = await vaultTools.search({ query: 'target', returnSnippets: true, snippetLength: 100 });
|
||||
|
||||
expect(result.isError).toBeUndefined();
|
||||
const parsed = JSON.parse(result.content[0].text);
|
||||
expect(parsed.matches[0].snippet.length).toBeLessThanOrEqual(100);
|
||||
});
|
||||
|
||||
it('should handle zero-width regex matches', async () => {
|
||||
const mockFile = createMockTFile('test.md');
|
||||
mockVault.getMarkdownFiles = jest.fn().mockReturnValue([mockFile]);
|
||||
mockVault.read = jest.fn().mockResolvedValue('test');
|
||||
|
||||
const result = await vaultTools.search({ query: '(?=test)', isRegex: true, maxResults: 10 });
|
||||
|
||||
expect(result.isError).toBeUndefined();
|
||||
// Should handle zero-width matches without infinite loop
|
||||
});
|
||||
|
||||
it('should handle general search errors', async () => {
|
||||
mockVault.getMarkdownFiles = jest.fn().mockImplementation(() => {
|
||||
throw new Error('Vault error');
|
||||
});
|
||||
|
||||
const result = await vaultTools.search({ query: 'test' });
|
||||
|
||||
expect(result.isError).toBe(true);
|
||||
expect(result.content[0].text).toContain('Search error');
|
||||
});
|
||||
});
|
||||
|
||||
describe('searchWaypoints', () => {
|
||||
it('should search for waypoints in vault', async () => {
|
||||
const mockFile = createMockTFile('test.md');
|
||||
mockApp.vault = {
|
||||
getMarkdownFiles: jest.fn().mockReturnValue([mockFile])
|
||||
} as any;
|
||||
|
||||
// Mock SearchUtils
|
||||
const SearchUtils = require('../src/utils/search-utils').SearchUtils;
|
||||
SearchUtils.searchWaypoints = jest.fn().mockResolvedValue([
|
||||
{ path: 'test.md', waypointRange: { start: 0, end: 10 } }
|
||||
]);
|
||||
|
||||
const result = await vaultTools.searchWaypoints();
|
||||
|
||||
expect(result.isError).toBeUndefined();
|
||||
const parsed = JSON.parse(result.content[0].text);
|
||||
expect(parsed.totalWaypoints).toBeDefined();
|
||||
expect(parsed.filesSearched).toBeDefined();
|
||||
});
|
||||
|
||||
it('should filter waypoints by folder', async () => {
|
||||
const mockFile1 = createMockTFile('folder1/test.md');
|
||||
const mockFile2 = createMockTFile('folder2/test.md');
|
||||
mockApp.vault = {
|
||||
getMarkdownFiles: jest.fn().mockReturnValue([mockFile1, mockFile2])
|
||||
} as any;
|
||||
|
||||
const SearchUtils = require('../src/utils/search-utils').SearchUtils;
|
||||
SearchUtils.searchWaypoints = jest.fn().mockResolvedValue([]);
|
||||
|
||||
const result = await vaultTools.searchWaypoints('folder1');
|
||||
|
||||
expect(result.isError).toBeUndefined();
|
||||
const parsed = JSON.parse(result.content[0].text);
|
||||
expect(parsed.filesSearched).toBe(1);
|
||||
});
|
||||
|
||||
it('should handle search errors', async () => {
|
||||
const SearchUtils = require('../src/utils/search-utils').SearchUtils;
|
||||
SearchUtils.searchWaypoints = jest.fn().mockRejectedValue(new Error('Search failed'));
|
||||
|
||||
const result = await vaultTools.searchWaypoints();
|
||||
|
||||
expect(result.isError).toBe(true);
|
||||
expect(result.content[0].text).toContain('Waypoint search error');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getFolderWaypoint', () => {
|
||||
it('should return error if file not found', async () => {
|
||||
const PathUtils = require('../src/utils/path-utils').PathUtils;
|
||||
PathUtils.resolveFile = jest.fn().mockReturnValue(null);
|
||||
|
||||
const result = await vaultTools.getFolderWaypoint('nonexistent.md');
|
||||
|
||||
expect(result.isError).toBe(true);
|
||||
expect(result.content[0].text).toContain('not found');
|
||||
});
|
||||
|
||||
it('should extract waypoint from file', async () => {
|
||||
const mockFile = createMockTFile('test.md');
|
||||
const PathUtils = require('../src/utils/path-utils').PathUtils;
|
||||
const WaypointUtils = require('../src/utils/waypoint-utils').WaypointUtils;
|
||||
|
||||
PathUtils.resolveFile = jest.fn().mockReturnValue(mockFile);
|
||||
mockApp.vault = {
|
||||
read: jest.fn().mockResolvedValue('%% Begin Waypoint %%\nContent\n%% End Waypoint %%')
|
||||
} as any;
|
||||
WaypointUtils.extractWaypointBlock = jest.fn().mockReturnValue({
|
||||
hasWaypoint: true,
|
||||
waypointRange: { start: 0, end: 10 },
|
||||
links: ['link1'],
|
||||
rawContent: 'Content'
|
||||
});
|
||||
|
||||
const result = await vaultTools.getFolderWaypoint('test.md');
|
||||
|
||||
expect(result.isError).toBeUndefined();
|
||||
const parsed = JSON.parse(result.content[0].text);
|
||||
expect(parsed.hasWaypoint).toBe(true);
|
||||
});
|
||||
|
||||
it('should handle errors', async () => {
|
||||
const PathUtils = require('../src/utils/path-utils').PathUtils;
|
||||
PathUtils.resolveFile = jest.fn().mockImplementation(() => {
|
||||
throw new Error('File error');
|
||||
});
|
||||
|
||||
const result = await vaultTools.getFolderWaypoint('test.md');
|
||||
|
||||
expect(result.isError).toBe(true);
|
||||
expect(result.content[0].text).toContain('Get folder waypoint error');
|
||||
});
|
||||
});
|
||||
|
||||
describe('isFolderNote', () => {
|
||||
it('should return error if file not found', async () => {
|
||||
const PathUtils = require('../src/utils/path-utils').PathUtils;
|
||||
PathUtils.resolveFile = jest.fn().mockReturnValue(null);
|
||||
|
||||
const result = await vaultTools.isFolderNote('nonexistent.md');
|
||||
|
||||
expect(result.isError).toBe(true);
|
||||
expect(result.content[0].text).toContain('not found');
|
||||
});
|
||||
|
||||
it('should detect folder notes', async () => {
|
||||
const mockFile = createMockTFile('test.md');
|
||||
const PathUtils = require('../src/utils/path-utils').PathUtils;
|
||||
const WaypointUtils = require('../src/utils/waypoint-utils').WaypointUtils;
|
||||
|
||||
PathUtils.resolveFile = jest.fn().mockReturnValue(mockFile);
|
||||
WaypointUtils.isFolderNote = jest.fn().mockResolvedValue({
|
||||
isFolderNote: true,
|
||||
reason: 'basename_match',
|
||||
folderPath: 'test'
|
||||
});
|
||||
|
||||
const result = await vaultTools.isFolderNote('test.md');
|
||||
|
||||
expect(result.isError).toBeUndefined();
|
||||
const parsed = JSON.parse(result.content[0].text);
|
||||
expect(parsed.isFolderNote).toBe(true);
|
||||
});
|
||||
|
||||
it('should handle errors', async () => {
|
||||
const PathUtils = require('../src/utils/path-utils').PathUtils;
|
||||
PathUtils.resolveFile = jest.fn().mockImplementation(() => {
|
||||
throw new Error('File error');
|
||||
});
|
||||
|
||||
const result = await vaultTools.isFolderNote('test.md');
|
||||
|
||||
expect(result.isError).toBe(true);
|
||||
expect(result.content[0].text).toContain('Is folder note error');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getBacklinks - unlinked mentions', () => {
|
||||
it('should find unlinked mentions', async () => {
|
||||
const targetFile = createMockTFile('target.md');
|
||||
const sourceFile = createMockTFile('source.md');
|
||||
|
||||
mockVault.getAbstractFileByPath = jest.fn()
|
||||
.mockReturnValueOnce(targetFile)
|
||||
.mockReturnValue(sourceFile);
|
||||
mockVault.read = jest.fn().mockResolvedValue('This mentions target in text');
|
||||
mockVault.getMarkdownFiles = jest.fn().mockReturnValue([sourceFile]);
|
||||
mockMetadata.resolvedLinks = {};
|
||||
|
||||
const result = await vaultTools.getBacklinks('target.md', true, true);
|
||||
|
||||
expect(result.isError).toBeUndefined();
|
||||
const parsed = JSON.parse(result.content[0].text);
|
||||
expect(parsed.backlinks.some((b: any) => b.type === 'unlinked')).toBe(true);
|
||||
});
|
||||
|
||||
it('should not return unlinked mentions when includeUnlinked is false', async () => {
|
||||
const targetFile = createMockTFile('target.md');
|
||||
|
||||
mockVault.getAbstractFileByPath = jest.fn().mockReturnValue(targetFile);
|
||||
mockMetadata.resolvedLinks = {};
|
||||
|
||||
const result = await vaultTools.getBacklinks('target.md', false, true);
|
||||
|
||||
expect(result.isError).toBeUndefined();
|
||||
const parsed = JSON.parse(result.content[0].text);
|
||||
expect(parsed.backlinks.every((b: any) => b.type !== 'unlinked')).toBe(true);
|
||||
});
|
||||
|
||||
it('should skip files that already have linked backlinks', async () => {
|
||||
const targetFile = createMockTFile('target.md');
|
||||
const sourceFile = createMockTFile('source.md');
|
||||
|
||||
mockVault.getAbstractFileByPath = jest.fn()
|
||||
.mockReturnValueOnce(targetFile)
|
||||
.mockReturnValue(sourceFile);
|
||||
mockVault.read = jest.fn().mockResolvedValue('This links to [[target]] and mentions target');
|
||||
mockVault.getMarkdownFiles = jest.fn().mockReturnValue([sourceFile]);
|
||||
mockMetadata.resolvedLinks = {
|
||||
'source.md': { 'target.md': 1 }
|
||||
};
|
||||
mockMetadata.getFirstLinkpathDest = jest.fn().mockReturnValue(targetFile);
|
||||
|
||||
const result = await vaultTools.getBacklinks('target.md', true, true);
|
||||
|
||||
expect(result.isError).toBeUndefined();
|
||||
const parsed = JSON.parse(result.content[0].text);
|
||||
// Should have linked mention but not duplicate unlinked
|
||||
expect(parsed.backlinks.filter((b: any) => b.sourcePath === 'source.md').length).toBe(1);
|
||||
});
|
||||
|
||||
it('should skip target file itself in unlinked mentions', async () => {
|
||||
const targetFile = createMockTFile('target.md');
|
||||
|
||||
mockVault.getAbstractFileByPath = jest.fn().mockReturnValue(targetFile);
|
||||
mockVault.read = jest.fn().mockResolvedValue('This file mentions target');
|
||||
mockVault.getMarkdownFiles = jest.fn().mockReturnValue([targetFile]);
|
||||
mockMetadata.resolvedLinks = {};
|
||||
|
||||
const result = await vaultTools.getBacklinks('target.md', true, true);
|
||||
|
||||
expect(result.isError).toBeUndefined();
|
||||
const parsed = JSON.parse(result.content[0].text);
|
||||
expect(parsed.backlinks.every((b: any) => b.sourcePath !== 'target.md')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('list - edge cases', () => {
|
||||
it('should handle invalid path in list', async () => {
|
||||
const result = await vaultTools.list({ path: '../invalid' });
|
||||
|
||||
expect(result.isError).toBe(true);
|
||||
expect(result.content[0].text).toContain('Invalid path');
|
||||
});
|
||||
|
||||
it('should handle non-existent folder', async () => {
|
||||
mockVault.getAbstractFileByPath = jest.fn().mockReturnValue(null);
|
||||
|
||||
const result = await vaultTools.list({ path: 'nonexistent' });
|
||||
|
||||
expect(result.isError).toBe(true);
|
||||
expect(result.content[0].text).toContain('not found');
|
||||
});
|
||||
|
||||
it('should handle path pointing to file instead of folder', async () => {
|
||||
const mockFile = createMockTFile('test.md');
|
||||
mockVault.getAbstractFileByPath = jest.fn().mockReturnValue(mockFile);
|
||||
|
||||
const result = await vaultTools.list({ path: 'test.md' });
|
||||
|
||||
expect(result.isError).toBe(true);
|
||||
expect(result.content[0].text).toContain('not a folder');
|
||||
});
|
||||
|
||||
it('should handle cursor not found in pagination', async () => {
|
||||
const mockFile = createMockTFile('test.md');
|
||||
const mockRoot = createMockTFolder('', [mockFile]);
|
||||
|
||||
mockVault.getRoot = jest.fn().mockReturnValue(mockRoot);
|
||||
|
||||
const result = await vaultTools.list({ cursor: 'nonexistent.md' });
|
||||
|
||||
expect(result.isError).toBeUndefined();
|
||||
const parsed = JSON.parse(result.content[0].text);
|
||||
// Should return from beginning when cursor not found
|
||||
expect(parsed.items.length).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user