keyword-search.test.mjs
105 lines 4.1 KB
Raw
sha256:41d741fb345c4abdb640838aa3d847de02ccffd7a39fce04894e743e683b50d0 fix(security): pin patched transitive deps to clear Dependa… Human minor ⚠ breaking 7 days ago
1 /**
2 * Keyword search: phrase, all_terms, folder, content_scope.
3 */
4 import { describe, it, before, after } from 'node:test';
5 import assert from 'node:assert';
6 import path from 'path';
7 import { fileURLToPath } from 'url';
8 import { loadConfig } from '../lib/config.mjs';
9 import { runKeywordSearch, keywordSearchNotesArray, noteRecordFromExportPayload } from '../lib/keyword-search.mjs';
10 import { filterNotesByListOptions } from '../lib/list-notes.mjs';
11
12 const __dirname = path.dirname(fileURLToPath(import.meta.url));
13 const fixturesDir = path.join(__dirname, 'fixtures');
14
15 describe('runKeywordSearch', () => {
16 const envBackup = {
17 KNOWTATION_VAULT_PATH: process.env.KNOWTATION_VAULT_PATH,
18 KNOWTATION_DATA_DIR: process.env.KNOWTATION_DATA_DIR,
19 };
20 const fixtureVaultAbs = path.join(fixturesDir, 'vault-fs');
21 let config;
22 before(() => {
23 process.env.KNOWTATION_VAULT_PATH = fixtureVaultAbs;
24 delete process.env.KNOWTATION_DATA_DIR;
25 config = loadConfig(fixturesDir);
26 });
27 after(() => {
28 if (envBackup.KNOWTATION_VAULT_PATH !== undefined) {
29 process.env.KNOWTATION_VAULT_PATH = envBackup.KNOWTATION_VAULT_PATH;
30 } else {
31 delete process.env.KNOWTATION_VAULT_PATH;
32 }
33 if (envBackup.KNOWTATION_DATA_DIR !== undefined) {
34 process.env.KNOWTATION_DATA_DIR = envBackup.KNOWTATION_DATA_DIR;
35 } else {
36 delete process.env.KNOWTATION_DATA_DIR;
37 }
38 });
39
40 it('matches phrase in body (case-insensitive)', async () => {
41 const out = await runKeywordSearch('inbox one', {}, config);
42 assert.strictEqual(out.mode, 'keyword');
43 const paths = (out.results || []).map((r) => r.path);
44 assert(paths.includes('inbox/one.md'));
45 });
46
47 it('matches all_terms (AND)', async () => {
48 const out = await runKeywordSearch('inbox two', { match: 'all_terms' }, config);
49 const paths = (out.results || []).map((r) => r.path);
50 assert(paths.includes('inbox/two.md'));
51 });
52
53 it('matches phrase in title frontmatter', async () => {
54 const out = await runKeywordSearch('Project note', {}, config);
55 const paths = (out.results || []).map((r) => r.path);
56 assert(paths.includes('projects/foo/note.md'));
57 });
58
59 it('filters by folder', async () => {
60 const out = await runKeywordSearch('Body', { folder: 'inbox' }, config);
61 const paths = (out.results || []).map((r) => r.path);
62 assert(paths.every((p) => p === 'inbox' || p.startsWith('inbox/')));
63 assert(!paths.some((p) => p.startsWith('projects/')));
64 });
65
66 it('content_scope notes excludes approval logs', async () => {
67 const all = await runKeywordSearch('approvaluniquekeyword', {}, config);
68 assert((all.results || []).some((r) => r.path.startsWith('approvals/')));
69 const notesOnly = await runKeywordSearch('approvaluniquekeyword', { content_scope: 'notes' }, config);
70 assert(!(notesOnly.results || []).some((r) => r.path.startsWith('approvals/')));
71 });
72
73 it('countOnly returns count', async () => {
74 const out = await runKeywordSearch('Body', { countOnly: true }, config);
75 assert.strictEqual(out.mode, 'keyword');
76 assert(typeof out.count === 'number');
77 assert.strictEqual(out.results, undefined);
78 });
79 });
80
81 describe('keywordSearchNotesArray + export payload', () => {
82 it('noteRecordFromExportPayload parses frontmatter JSON string', () => {
83 const rec = noteRecordFromExportPayload({
84 path: 'x.md',
85 body: 'hello',
86 frontmatter: JSON.stringify({ title: 'T', tags: ['z'], project: 'p' }),
87 });
88 assert.strictEqual(rec.path, 'x.md');
89 assert.strictEqual(rec.body, 'hello');
90 assert.strictEqual(rec.frontmatter.title, 'T');
91 });
92
93 it('filters export-shaped notes like list-notes', () => {
94 const raw = [
95 { path: 'inbox/a.md', body: 'alpha beta', frontmatter: '{}' },
96 { path: 'projects/foo/b.md', body: 'alpha only here', frontmatter: '{}' },
97 ];
98 const notes = raw.map(noteRecordFromExportPayload);
99 const filtered = filterNotesByListOptions(notes, { folder: 'inbox' });
100 assert.strictEqual(filtered.length, 1);
101 assert.strictEqual(filtered[0].path, 'inbox/a.md');
102 const out = keywordSearchNotesArray(filtered, 'alpha beta', { limit: 10 });
103 assert.strictEqual(out.results?.length, 1);
104 });
105 });
File History 1 commit
sha256:41d741fb345c4abdb640838aa3d847de02ccffd7a39fce04894e743e683b50d0 fix(security): pin patched transitive deps to clear Dependa… Human minor 7 days ago