import { FoamGraph } from '../model/graph'; import { Logger } from '../utils/log'; import { createTestNote, createTestWorkspace } from '../../test/test-utils'; import { renderDqlQuery } from './dql'; import { createMarkdownParser } from '../services/markdown-parser'; import { URI } from '../model/uri'; Logger.setLevel('error'); function makeWorkspaceAndGraph(notes: ReturnType[]) { const workspace = createTestWorkspace(); notes.forEach(n => workspace.set(n)); const graph = FoamGraph.fromWorkspace(workspace, false); return { workspace, graph }; } describe('renderDqlQuery — warning escaping', () => { it('escapes user-controlled filter text in warnings to prevent HTML injection', () => { const { workspace, graph } = makeWorkspaceAndGraph([ createTestNote({ uri: '/a.md' }), ]); // The filter targets a note identifier containing an HTML payload. The // resulting "not found" warning embeds this string; if it were rendered // unescaped the preview would inject the tag into the DOM. const { html } = renderDqlQuery( `filter:\n links_to: ''`, { workspace, graph, trusted: false, toHref: uri => uri.path } ); expect(html).not.toContain(' { const { workspace, graph } = makeWorkspaceAndGraph([ createTestNote({ uri: '/a.md' }), ]); const { html } = renderDqlQuery( `filter:\n path: '\n` ); const { html } = renderDqlQuery(`filter: '*'\nselect: [body]`, { workspace, graph, trusted: false, toHref: uri => uri.path, readSource: () => markdown, // no renderMarkdown }); expect(html).not.toContain(''`, `format: table`, ].join('\n'), { workspace, graph, trusted: false, toHref: uri => uri.path } ); expect(html).not.toContain(''); expect(html).toContain('<script>x</script>'); }); it('keeps sort working against the raw field expression when a label is set', () => { const { workspace, graph } = makeWorkspaceAndGraph([ createTestNote({ uri: '/a.md', title: 'A', properties: { rank: 2 } }), createTestNote({ uri: '/b.md', title: 'B', properties: { rank: 1 } }), ]); const { html } = renderDqlQuery( [ `filter: '*'`, `select:`, ` - title`, ` - field: properties.rank`, ` label: Rank`, `sort: properties.rank ASC`, `format: table`, ].join('\n'), { workspace, graph, trusted: false, toHref: uri => uri.path } ); // First data row should be B (rank 1) const firstRowIdx = html.indexOf(''); const tbody = html.slice(firstRowIdx); const firstRow = tbody.slice(0, tbody.indexOf('')); expect(firstRow).toContain('>B<'); }); it('rejects an object entry without a `field` key', () => { const { workspace, graph } = makeWorkspaceAndGraph([ createTestNote({ uri: '/a.md', title: 'A' }), ]); const { html } = renderDqlQuery( [ `filter: '*'`, `select:`, ` - title`, ` - label: orphan`, `format: table`, ].join('\n'), { workspace, graph, trusted: false, toHref: uri => uri.path } ); expect(html).toContain('Unknown select field'); }); });