|
1 | 1 | import type { SearchSnippet } from '../../src/retriv/types' |
2 | 2 | import { describe, expect, it } from 'vitest' |
3 | | -import { parseFilterPrefix } from '../../src/commands/search' |
| 3 | +import { generateSearchGuide, parseFilterPrefix, parseJsonFilter } from '../../src/commands/search' |
4 | 4 | import { normalizeScores, scoreLabel } from '../../src/core/formatting' |
5 | 5 |
|
6 | 6 | function snippet(overrides: Partial<SearchSnippet> = {}): SearchSnippet { |
@@ -57,6 +57,97 @@ describe('parseFilterPrefix', () => { |
57 | 57 | }) |
58 | 58 | }) |
59 | 59 |
|
| 60 | +describe('parseJsonFilter', () => { |
| 61 | + it('parses valid JSON object', () => { |
| 62 | + expect(parseJsonFilter('{"type":"issue"}')).toEqual({ type: 'issue' }) |
| 63 | + }) |
| 64 | + |
| 65 | + it('parses filter with operators', () => { |
| 66 | + expect(parseJsonFilter('{"type":{"$in":["doc","issue"]}}')).toEqual({ |
| 67 | + type: { $in: ['doc', 'issue'] }, |
| 68 | + }) |
| 69 | + }) |
| 70 | + |
| 71 | + it('parses $prefix operator', () => { |
| 72 | + expect(parseJsonFilter('{"source":{"$prefix":"docs/api/"}}')).toEqual({ |
| 73 | + source: { $prefix: 'docs/api/' }, |
| 74 | + }) |
| 75 | + }) |
| 76 | + |
| 77 | + it('parses numeric operators', () => { |
| 78 | + expect(parseJsonFilter('{"number":{"$gt":100}}')).toEqual({ |
| 79 | + number: { $gt: 100 }, |
| 80 | + }) |
| 81 | + }) |
| 82 | + |
| 83 | + it('parses $exists operator', () => { |
| 84 | + expect(parseJsonFilter('{"number":{"$exists":true}}')).toEqual({ |
| 85 | + number: { $exists: true }, |
| 86 | + }) |
| 87 | + }) |
| 88 | + |
| 89 | + it('parses multiple fields', () => { |
| 90 | + expect(parseJsonFilter('{"type":"issue","number":{"$lt":50}}')).toEqual({ |
| 91 | + type: 'issue', |
| 92 | + number: { $lt: 50 }, |
| 93 | + }) |
| 94 | + }) |
| 95 | + |
| 96 | + it('returns null for invalid JSON', () => { |
| 97 | + expect(parseJsonFilter('not json')).toBeNull() |
| 98 | + }) |
| 99 | + |
| 100 | + it('returns null for JSON array', () => { |
| 101 | + expect(parseJsonFilter('[1,2,3]')).toBeNull() |
| 102 | + }) |
| 103 | + |
| 104 | + it('returns null for JSON string', () => { |
| 105 | + expect(parseJsonFilter('"hello"')).toBeNull() |
| 106 | + }) |
| 107 | + |
| 108 | + it('returns null for JSON number', () => { |
| 109 | + expect(parseJsonFilter('42')).toBeNull() |
| 110 | + }) |
| 111 | + |
| 112 | + it('returns null for JSON null', () => { |
| 113 | + expect(parseJsonFilter('null')).toBeNull() |
| 114 | + }) |
| 115 | +}) |
| 116 | + |
| 117 | +describe('generateSearchGuide', () => { |
| 118 | + it('generates generic guide without package', () => { |
| 119 | + const guide = generateSearchGuide() |
| 120 | + expect(guide).toContain('skilld search guide') |
| 121 | + expect(guide).toContain('-p <package>') |
| 122 | + expect(guide).toContain('$prefix') |
| 123 | + expect(guide).toContain('$in') |
| 124 | + expect(guide).toContain('--filter') |
| 125 | + expect(guide).toContain('--limit') |
| 126 | + }) |
| 127 | + |
| 128 | + it('tailors guide to specific package', () => { |
| 129 | + const guide = generateSearchGuide('vue') |
| 130 | + expect(guide).toContain('Search guide for vue') |
| 131 | + expect(guide).toContain('-p vue') |
| 132 | + expect(guide).toContain('e.g. "vue"') |
| 133 | + expect(guide).not.toContain('<package>') |
| 134 | + }) |
| 135 | + |
| 136 | + it('includes all metadata fields', () => { |
| 137 | + const guide = generateSearchGuide() |
| 138 | + expect(guide).toContain('package') |
| 139 | + expect(guide).toContain('source') |
| 140 | + expect(guide).toContain('type') |
| 141 | + expect(guide).toContain('number') |
| 142 | + }) |
| 143 | + |
| 144 | + it('includes all filter operators', () => { |
| 145 | + const guide = generateSearchGuide() |
| 146 | + for (const op of ['$eq', '$ne', '$gt', '$gte', '$lt', '$lte', '$in', '$prefix', '$exists']) |
| 147 | + expect(guide).toContain(op) |
| 148 | + }) |
| 149 | +}) |
| 150 | + |
60 | 151 | describe('normalizeScores', () => { |
61 | 152 | it('normalizes best result to 100', () => { |
62 | 153 | const results = [snippet({ score: 0.08 }), snippet({ score: 0.04 }), snippet({ score: 0.02 })] |
|
0 commit comments