MediBot / __tests__ /rag /query.test.ts
github-actions[bot]
Deploy MedOS Global from 956ae78f
e3e3e14
Raw
History Blame Contribute Delete
2.11 kB
import { describe, it, expect } from 'vitest';
import { normalizeQuery, queryTerms, buildFtsMatch } from '@/lib/rag/query';
describe('normalizeQuery', () => {
it('collapses whitespace and trims', () => {
expect(normalizeQuery(' chest pain\n\there ')).toBe('chest pain here');
});
it('caps length at 500 chars', () => {
expect(normalizeQuery('a'.repeat(900)).length).toBe(500);
});
it('handles empty / nullish input', () => {
expect(normalizeQuery('')).toBe('');
// @ts-expect-error — defensive: tolerate undefined at runtime
expect(normalizeQuery(undefined)).toBe('');
});
});
describe('queryTerms', () => {
it('drops stopwords and short tokens, lowercases, dedupes', () => {
const terms = queryTerms('What are the BEST best treatments for pain');
expect(terms).toContain('best');
expect(terms).toContain('treatments');
expect(terms).toContain('pain');
expect(terms).not.toContain('the'); // stopword
expect(terms).not.toContain('for'); // stopword
// de-duplicated
expect(terms.filter((t) => t === 'best')).toHaveLength(1);
});
it('returns [] when nothing usable remains', () => {
expect(queryTerms('the and a an ?? !!')).toEqual([]);
});
});
describe('buildFtsMatch (FTS5 injection safety)', () => {
it('produces only quoted terms joined by OR', () => {
const m = buildFtsMatch('chest pain breathing');
expect(m).toMatch(/^"[a-z0-9]+"( OR "[a-z0-9]+")*$/);
expect(m).toContain('"chest"');
});
it('neutralises FTS operators and punctuation', () => {
// Raw input that would throw or inject if passed to MATCH verbatim.
const m = buildFtsMatch('x" OR rag_chunks_fts MATCH "y NEAR(z) -drop');
// No unbalanced quotes; every quote belongs to a "token" wrapper.
expect((m.match(/"/g) || []).length % 2).toBe(0);
// Only quoted-alnum-OR structure survives — no bare operators/quotes.
if (m) expect(m).toMatch(/^"[a-z0-9]+"( OR "[a-z0-9]+")*$/);
});
it('returns empty string when there are no usable terms', () => {
expect(buildFtsMatch('?? a an')).toBe('');
});
});