feat(05-02): exa-search research integration
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const express = require('express');
|
||||
const request = require('supertest');
|
||||
const { createExerciseResearchRouter } = require('../../src/routes/exerciseResearch');
|
||||
|
||||
const buildPoolMock = ({ exerciseRow }) => ({
|
||||
query: async (text) => {
|
||||
if (text.includes('FROM exercises')) {
|
||||
return { rows: exerciseRow ? [exerciseRow] : [] };
|
||||
}
|
||||
if (text.includes('INSERT INTO research_results')) {
|
||||
return { rows: [{ id: 1, created_at: '2026-03-02T00:00:00.000Z' }] };
|
||||
}
|
||||
return { rows: [] };
|
||||
}
|
||||
});
|
||||
|
||||
const buildApp = ({ pool, exaSearch }) => {
|
||||
const app = express();
|
||||
app.use(express.json());
|
||||
app.use('/api/exercises', createExerciseResearchRouter({ pool, exaSearch }));
|
||||
return app;
|
||||
};
|
||||
|
||||
test('Exercise research returns summary and results', async () => {
|
||||
const pool = buildPoolMock({
|
||||
exerciseRow: {
|
||||
id: 1,
|
||||
name: 'Bench Press',
|
||||
description: 'Barbell press'
|
||||
}
|
||||
});
|
||||
|
||||
const exaSearch = async ({ query, numResults }) => ({
|
||||
summary: `Summary for ${query} (${numResults})`,
|
||||
results: [
|
||||
{ title: 'Guide', url: 'https://example.com', snippet: 'Bench press form.' }
|
||||
]
|
||||
});
|
||||
|
||||
const app = buildApp({ pool, exaSearch });
|
||||
const response = await request(app)
|
||||
.post('/api/exercises/1/research')
|
||||
.send({ query: 'Bench press technique', num_results: 3 });
|
||||
|
||||
assert.equal(response.statusCode, 200);
|
||||
assert.equal(response.body.exercise.id, 1);
|
||||
assert.equal(response.body.summary, 'Summary for Bench press technique (3)');
|
||||
assert.equal(response.body.results.length, 1);
|
||||
assert.ok(response.body.stored);
|
||||
});
|
||||
|
||||
test('Exercise research returns 404 when exercise missing', async () => {
|
||||
const pool = buildPoolMock({ exerciseRow: null });
|
||||
const exaSearch = async () => {
|
||||
throw new Error('Should not call exa');
|
||||
};
|
||||
|
||||
const app = buildApp({ pool, exaSearch });
|
||||
const response = await request(app)
|
||||
.post('/api/exercises/999/research')
|
||||
.send({ query: 'Missing' });
|
||||
|
||||
assert.equal(response.statusCode, 404);
|
||||
assert.equal(response.body.error, 'Exercise not found');
|
||||
});
|
||||
|
||||
test('Exercise research validates id', async () => {
|
||||
const pool = buildPoolMock({ exerciseRow: null });
|
||||
const exaSearch = async () => ({ summary: '', results: [] });
|
||||
|
||||
const app = buildApp({ pool, exaSearch });
|
||||
const response = await request(app)
|
||||
.post('/api/exercises/not-a-number/research')
|
||||
.send({ query: 'Bench' });
|
||||
|
||||
assert.equal(response.statusCode, 400);
|
||||
assert.equal(response.body.error, 'Exercise id must be an integer');
|
||||
});
|
||||
Reference in New Issue
Block a user