feat: solution for 'Повторный экзамен #2: Сравнительный обзор 3 сущностей (Tavily)'
This commit is contained in:
+54
-31
@@ -1,48 +1,71 @@
|
||||
const { compareEntities } = require('../src/index');
|
||||
const axios = require('axios');
|
||||
|
||||
jest.mock('axios');
|
||||
const nock = require('nock');
|
||||
const { compareEntities } = require('../src/compare');
|
||||
require('dotenv').config({ path: '.env.example' });
|
||||
|
||||
describe('compareEntities', () => {
|
||||
const mockResponse = {
|
||||
status: 200,
|
||||
data: {
|
||||
results: [
|
||||
{ title: 'Apple vs Samsung vs Google', content: 'Apple leads in design...' },
|
||||
],
|
||||
},
|
||||
};
|
||||
const baseUrl = 'https://api.tavily.com';
|
||||
const apiKey = 'test-key';
|
||||
|
||||
beforeEach(() => {
|
||||
axios.post.mockResolvedValue(mockResponse);
|
||||
beforeAll(() => {
|
||||
process.env.TAVILY_API_KEY = apiKey;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
nock.cleanAll();
|
||||
});
|
||||
|
||||
it('should return data from Tavily API', async () => {
|
||||
const data = await compareEntities('Apple', 'Samsung', 'Google');
|
||||
expect(data).toEqual(mockResponse.data);
|
||||
expect(axios.post).toHaveBeenCalledWith(
|
||||
'https://api.tavily.com/search',
|
||||
expect.objectContaining({
|
||||
query: expect.stringContaining('Apple'),
|
||||
}),
|
||||
expect.any(Object)
|
||||
test('returns ranked results based on number of results', async () => {
|
||||
nock(baseUrl)
|
||||
.post('/search', { query: 'entity1' })
|
||||
.reply(200, { results: [{}, {}] }); // 2 results
|
||||
nock(baseUrl)
|
||||
.post('/search', { query: 'entity2' })
|
||||
.reply(200, { results: [{}, {}, {}] }); // 3 results
|
||||
nock(baseUrl)
|
||||
.post('/search', { query: 'entity3' })
|
||||
.reply(200, { results: [{}, {}] }); // 2 results
|
||||
|
||||
const result = await compareEntities('entity1', 'entity2', 'entity3');
|
||||
expect(result.ranked[0].entity).toBe('entity2');
|
||||
expect(result.ranked[1].entity).toBe('entity1');
|
||||
expect(result.ranked[2].entity).toBe('entity3');
|
||||
});
|
||||
|
||||
test('throws error on empty entity', async () => {
|
||||
await expect(compareEntities('', 'b', 'c')).rejects.toThrow(
|
||||
'All entities must be non-empty strings.'
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw error if any entity is missing', async () => {
|
||||
await expect(compareEntities('Apple', '', 'Google')).rejects.toThrow(
|
||||
'All three entity names must be provided.'
|
||||
test('handles API error', async () => {
|
||||
nock(baseUrl)
|
||||
.post('/search', { query: 'entity1' })
|
||||
.reply(401, { error: 'Invalid API key' });
|
||||
nock(baseUrl)
|
||||
.post('/search', { query: 'entity2' })
|
||||
.reply(200, { results: [] });
|
||||
nock(baseUrl)
|
||||
.post('/search', { query: 'entity3' })
|
||||
.reply(200, { results: [] });
|
||||
|
||||
await expect(compareEntities('entity1', 'entity2', 'entity3')).rejects.toThrow(
|
||||
'Tavily API error: 401 Invalid API key'
|
||||
);
|
||||
});
|
||||
|
||||
it('should propagate API errors', async () => {
|
||||
axios.post.mockRejectedValue(new Error('Network error'));
|
||||
await expect(compareEntities('Apple', 'Samsung', 'Google')).rejects.toThrow(
|
||||
'Network error'
|
||||
test('handles network failure', async () => {
|
||||
nock(baseUrl)
|
||||
.post('/search', { query: 'entity1' })
|
||||
.replyWithError('Network down');
|
||||
nock(baseUrl)
|
||||
.post('/search', { query: 'entity2' })
|
||||
.reply(200, { results: [] });
|
||||
nock(baseUrl)
|
||||
.post('/search', { query: 'entity3' })
|
||||
.reply(200, { results: [] });
|
||||
|
||||
await expect(compareEntities('entity1', 'entity2', 'entity3')).rejects.toThrow(
|
||||
'Network error: Network down'
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user