All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 33s
CI / test-python-backend-compliance (push) Successful in 27s
CI / test-python-document-crawler (push) Successful in 20s
CI / test-python-dsms-gateway (push) Successful in 16s
- Add rag-query.test.ts (7 Jest tests for shared queryRAG utility) - Add test_routes_legal_context.py (3 tests for ?include_legal_context param) - Update ARCHITECTURE.md with multi-collection RAG section (3.3) - Update DEVELOPER.md with RAG usage examples, collection table, error tolerance - Add SDK flow page with updated requirements + DSFA RAG descriptions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
112 lines
2.8 KiB
TypeScript
112 lines
2.8 KiB
TypeScript
/**
|
|
* Tests for the shared queryRAG utility.
|
|
*/
|
|
|
|
// Mock fetch globally before importing
|
|
const mockFetch = jest.fn()
|
|
global.fetch = mockFetch
|
|
|
|
// Reset modules to pick up our mock
|
|
jest.resetModules()
|
|
|
|
describe('queryRAG', () => {
|
|
let queryRAG: (query: string, topK?: number) => Promise<string>
|
|
|
|
beforeEach(async () => {
|
|
jest.resetModules()
|
|
mockFetch.mockReset()
|
|
// Dynamic import to pick up fresh env
|
|
const mod = await import('../rag-query')
|
|
queryRAG = mod.queryRAG
|
|
})
|
|
|
|
it('should return formatted results on success', async () => {
|
|
mockFetch.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: async () => ({
|
|
results: [
|
|
{ source_name: 'DSGVO', content: 'Art. 35 regelt die DSFA...' },
|
|
{ source_code: 'EU_2016_679', content: 'Risikobewertung erforderlich' },
|
|
],
|
|
}),
|
|
})
|
|
|
|
const result = await queryRAG('DSFA Art. 35')
|
|
|
|
expect(result).toContain('[Quelle 1: DSGVO]')
|
|
expect(result).toContain('Art. 35 regelt die DSFA...')
|
|
expect(result).toContain('[Quelle 2: EU_2016_679]')
|
|
expect(mockFetch).toHaveBeenCalledTimes(1)
|
|
})
|
|
|
|
it('should return empty string on HTTP error', async () => {
|
|
mockFetch.mockResolvedValueOnce({
|
|
ok: false,
|
|
status: 500,
|
|
})
|
|
|
|
const result = await queryRAG('test query')
|
|
|
|
expect(result).toBe('')
|
|
})
|
|
|
|
it('should return empty string on network error', async () => {
|
|
mockFetch.mockRejectedValueOnce(new Error('Connection refused'))
|
|
|
|
const result = await queryRAG('test query')
|
|
|
|
expect(result).toBe('')
|
|
})
|
|
|
|
it('should return empty string when no results', async () => {
|
|
mockFetch.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: async () => ({ results: [] }),
|
|
})
|
|
|
|
const result = await queryRAG('test query')
|
|
|
|
expect(result).toBe('')
|
|
})
|
|
|
|
it('should pass topK parameter in URL', async () => {
|
|
mockFetch.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: async () => ({ results: [] }),
|
|
})
|
|
|
|
await queryRAG('test query', 7)
|
|
|
|
const calledUrl = mockFetch.mock.calls[0][0] as string
|
|
expect(calledUrl).toContain('top_k=7')
|
|
})
|
|
|
|
it('should use default topK of 3', async () => {
|
|
mockFetch.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: async () => ({ results: [] }),
|
|
})
|
|
|
|
await queryRAG('test query')
|
|
|
|
const calledUrl = mockFetch.mock.calls[0][0] as string
|
|
expect(calledUrl).toContain('top_k=3')
|
|
})
|
|
|
|
it('should handle results with missing fields gracefully', async () => {
|
|
mockFetch.mockResolvedValueOnce({
|
|
ok: true,
|
|
json: async () => ({
|
|
results: [
|
|
{ content: 'Some content without source' },
|
|
],
|
|
}),
|
|
})
|
|
|
|
const result = await queryRAG('test')
|
|
|
|
expect(result).toContain('[Quelle 1: Unbekannt]')
|
|
expect(result).toContain('Some content without source')
|
|
})
|
|
})
|