import { describe, expect, it } from 'vitest'; import { filterComment, filterGroup, filterPage, filterSearchResult, filterSpace, filterWorkspace, } from '../packages/docmost-client/src/lib/filters.js'; describe('filterPage', () => { const basePage = { id: 'pg1', slugId: 'slug-1', title: 'Title', parentPageId: 'parent-1', spaceId: 'space-1', isLocked: false, createdAt: '2024-01-01', updatedAt: '2024-01-02', deletedAt: null, // Extra fields that must be dropped by the filter. secret: 'should-not-leak', }; it('omits the content key when no content arg is given', () => { const result = filterPage(basePage); expect(result).not.toHaveProperty('content'); expect(result).not.toHaveProperty('secret'); expect(result.id).toBe('pg1'); }); it('includes an empty-string content (truthiness trap: empty string is kept)', () => { const result = filterPage(basePage, ''); expect(result).toHaveProperty('content'); expect(result.content).toBe(''); }); it('includes a non-empty content string', () => { const result = filterPage(basePage, '# Markdown'); expect(result.content).toBe('# Markdown'); }); it('omits content when it is not a string', () => { // A non-string (e.g. an object passed by mistake) must be dropped. const result = filterPage(basePage, { junk: true } as unknown as string); expect(result).not.toHaveProperty('content'); }); it('omits subpages when undefined', () => { const result = filterPage(basePage); expect(result).not.toHaveProperty('subpages'); }); it('omits subpages when empty array', () => { const result = filterPage(basePage, undefined, []); expect(result).not.toHaveProperty('subpages'); }); it('maps non-empty subpages to { id, title } only', () => { const result = filterPage(basePage, undefined, [ { id: 's1', title: 'Sub 1', extra: 'drop-me' }, { id: 's2', title: 'Sub 2' }, ]); expect(result.subpages).toEqual([ { id: 's1', title: 'Sub 1' }, { id: 's2', title: 'Sub 2' }, ]); }); }); describe('filterComment', () => { const baseComment = { id: 'c1', pageId: 'pg1', content: 'original content', creatorId: 'u1', createdAt: '2024-01-01', }; it('overrides comment.content with markdownContent when provided', () => { const result = filterComment(baseComment, 'markdown version'); expect(result.content).toBe('markdown version'); }); it('falls back to comment.content when markdownContent is undefined', () => { const result = filterComment(baseComment, undefined); expect(result.content).toBe('original content'); }); it('keeps an empty-string markdownContent (uses ?? not ||)', () => { // `??` only falls back on null/undefined, so "" must be preserved. const result = filterComment(baseComment, ''); expect(result.content).toBe(''); }); it('applies defaults for selection/type/parentCommentId/editedAt/resolvedAt/resolvedById', () => { const result = filterComment(baseComment); expect(result.selection).toBeNull(); expect(result.type).toBe('page'); expect(result.parentCommentId).toBeNull(); expect(result.editedAt).toBeNull(); expect(result.resolvedAt).toBeNull(); expect(result.resolvedById).toBeNull(); }); it('passes through provided optional values', () => { const result = filterComment({ ...baseComment, selection: 'some text', type: 'inline', parentCommentId: 'c0', editedAt: '2024-02-01', resolvedAt: '2024-03-01', resolvedById: 'u9', }); expect(result.selection).toBe('some text'); expect(result.type).toBe('inline'); expect(result.parentCommentId).toBe('c0'); expect(result.editedAt).toBe('2024-02-01'); expect(result.resolvedAt).toBe('2024-03-01'); expect(result.resolvedById).toBe('u9'); }); it('returns null for creatorName when creator is absent', () => { const result = filterComment(baseComment); expect(result.creatorName).toBeNull(); }); it('reads the nested creator?.name when present', () => { const result = filterComment({ ...baseComment, creator: { name: 'Alice' }, }); expect(result.creatorName).toBe('Alice'); }); }); describe('filterSearchResult', () => { const baseResult = { id: 'r1', title: 'Result', parentPageId: 'p0', createdAt: '2024-01-01', updatedAt: '2024-01-02', rank: 0.9, highlight: 'Result', }; it('reads nested space?.id and space?.name when space is present', () => { const result = filterSearchResult({ ...baseResult, space: { id: 'sp1', name: 'Space One' }, }); expect(result.spaceId).toBe('sp1'); expect(result.spaceName).toBe('Space One'); }); it('returns undefined for space fields when space is absent (no throw)', () => { const result = filterSearchResult(baseResult); expect(result.spaceId).toBeUndefined(); expect(result.spaceName).toBeUndefined(); }); }); describe('flat pluckers (no branching)', () => { it('filterWorkspace plucks the expected shape', () => { const result = filterWorkspace({ id: 'w1', name: 'WS', description: 'desc', defaultSpaceId: 'sp1', createdAt: '2024-01-01', updatedAt: '2024-01-02', deletedAt: null, extra: 'drop', }); expect(result).toEqual({ id: 'w1', name: 'WS', description: 'desc', defaultSpaceId: 'sp1', createdAt: '2024-01-01', updatedAt: '2024-01-02', deletedAt: null, }); }); it('filterSpace plucks the expected shape', () => { const result = filterSpace({ id: 'sp1', name: 'Space', description: 'desc', slug: 'space', visibility: 'open', createdAt: '2024-01-01', updatedAt: '2024-01-02', deletedAt: null, extra: 'drop', }); expect(result).toEqual({ id: 'sp1', name: 'Space', description: 'desc', slug: 'space', visibility: 'open', createdAt: '2024-01-01', updatedAt: '2024-01-02', deletedAt: null, }); }); it('filterGroup plucks the expected shape', () => { const result = filterGroup({ id: 'g1', name: 'Group', description: 'desc', workspaceId: 'w1', createdAt: '2024-01-01', updatedAt: '2024-01-02', deletedAt: null, extra: 'drop', }); expect(result).toEqual({ id: 'g1', name: 'Group', description: 'desc', workspaceId: 'w1', createdAt: '2024-01-01', updatedAt: '2024-01-02', deletedAt: null, }); }); });