File size: 1,673 Bytes
07d9d6b
5a81b95
 
 
 
 
07d9d6b
 
 
 
 
 
 
 
5a81b95
 
07d9d6b
 
 
5a81b95
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import { describe, it, expect, vi, afterEach } from 'vitest';
import { fetchSecurityFeeds, ingestFeed, pollCertEu } from './securityApi';
import axios from 'axios';
import { mcpClient } from '../mcpClient';  // Mock

vi.mock('axios');
vi.mock('../mcpClient', () => ({
  mcpClient: {
    call: vi.fn(),
    emit: vi.fn(),
    on: vi.fn(),
    off: vi.fn()
  }
}));

describe('SecurityApi', () => {
  afterEach(() => {
    vi.clearAllMocks();
  });
  it('fetches real feeds via MCP, falls back on error', async () => {
    vi.mocked(mcpClient.call).mockResolvedValue({ payload: { feeds: [] } });
    const data = await fetchSecurityFeeds();
    expect(data).toHaveProperty('feeds');

    vi.mocked(mcpClient.call).mockRejectedValue(new Error('Fail'));
    const fallback = await fetchSecurityFeeds();
    expect(fallback).toHaveProperty('documentsIndexed', 98231);  // From fallback
  });

  it('ingests feed with dedupe and emits event', async () => {
    vi.mocked(mcpClient.call).mockResolvedValue({ payload: { deduped: true } });
    vi.mocked(mcpClient.emit).mockResolvedValue(undefined);

    await ingestFeed('test-feed', { data: 'test' });
    expect(vi.mocked(mcpClient.call)).toHaveBeenCalledWith('srag.dedupe', expect.any(Object));
    expect(vi.mocked(mcpClient.emit)).toHaveBeenCalledWith('feed-update', expect.objectContaining({ type: 'personal-hybrid' }));
  });

  it('polls CERT-EU RSS', async () => {
    vi.mocked(axios.get).mockResolvedValue({ data: '<rss><item><title>Test Advisory</title></item></rss>' });
    const items = await pollCertEu();
    expect(items).toHaveLength(1);
    expect(items[0]).toHaveProperty('title', 'Test Advisory');
  });
});