commit
32a36cceff
444 files changed
+67186
No files matched your search
@@ -0,0 +1,144 @@
|
||||
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
||||
const express = require('express');
|
||||
|
||||
// Mock dependencies of backend/routes/aiInsights.js before loading it
|
||||
vi.mock('../models/AiInsight.js', () => {
|
||||
return {
|
||||
getByCycleAndKandang: vi.fn(),
|
||||
upsert: vi.fn(),
|
||||
cleanupExpired: vi.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock('../services/dashboardInsightService.js', () => {
|
||||
return {
|
||||
generateDashboardInsight: vi.fn(),
|
||||
INSIGHT_VERSION: 'v1',
|
||||
};
|
||||
});
|
||||
|
||||
// Mock database module so it doesn't attempt real connection during test
|
||||
vi.mock('../database/db', () => ({}));
|
||||
|
||||
// Import express router
|
||||
const router = require('./aiInsights.js');
|
||||
|
||||
describe('AI Insights Proxy Route', () => {
|
||||
let app;
|
||||
|
||||
beforeEach(() => {
|
||||
vi.resetAllMocks();
|
||||
app = express();
|
||||
app.use(express.json());
|
||||
app.use('/api/ai-insights', router);
|
||||
});
|
||||
|
||||
it('should accept contextData and send it to LM Studio proxy with CP707 chunks', async () => {
|
||||
// 1. Mock fetch globally
|
||||
const mockResponseText = JSON.stringify({
|
||||
choices: [
|
||||
{
|
||||
message: {
|
||||
content: JSON.stringify({
|
||||
headline: 'Analisis Test FCR',
|
||||
status: 'ok',
|
||||
summary: ['FCR normal'],
|
||||
risks: [],
|
||||
actions: ['Pertahankan'],
|
||||
}),
|
||||
},
|
||||
finish_reason: 'stop',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const mockFetch = vi.fn().mockImplementation((url, options) => {
|
||||
// Mock /api/v1/models (checking loaded models)
|
||||
if (url.includes('/api/v1/models')) {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
json: () => Promise.resolve({ data: [{ id: 'mock-model' }] }),
|
||||
});
|
||||
}
|
||||
|
||||
// Mock RAG Service on port 5002
|
||||
if (url.includes(':5002/query')) {
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
json: () => Promise.resolve({
|
||||
chunks: ['Ini adalah chunk standar FCR broiler CP 707 dari buku.'],
|
||||
sources: ['page 1'],
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
// Mock LM Studio chat completions
|
||||
if (url.includes('/v1/chat/completions')) {
|
||||
const body = JSON.parse(options.body);
|
||||
|
||||
// Assert that body.messages contains system prompt with RAG chunks
|
||||
expect(body.messages[0].role).toBe('system');
|
||||
expect(body.messages[0].content).toContain('REFERENSI BUKU: Manajemen Broiler CP 707');
|
||||
expect(body.messages[0].content).toContain('Ini adalah chunk standar FCR broiler CP 707 dari buku.');
|
||||
|
||||
// Assert that body.messages contains user message with contextData
|
||||
expect(body.messages[1].role).toBe('user');
|
||||
expect(body.messages[1].content).toContain('"FCR_aktual": 1.25');
|
||||
|
||||
return Promise.resolve({
|
||||
ok: true,
|
||||
json: () => Promise.resolve(JSON.parse(mockResponseText)),
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.reject(new Error(`Unhandled fetch url: ${url}`));
|
||||
});
|
||||
|
||||
global.fetch = mockFetch;
|
||||
|
||||
// Simulate calling the endpoint using standard express request-response handling
|
||||
const req = {
|
||||
method: 'POST',
|
||||
url: '/api/ai-insights/proxy',
|
||||
headers: { 'content-type': 'application/json' },
|
||||
body: {
|
||||
topic: 'fcr',
|
||||
context_query: 'FCR standar broiler CP707',
|
||||
input: 'Data: FCR_aktual 1.25',
|
||||
contextData: { FCR_aktual: 1.25 },
|
||||
system_prompt: 'Anda adalah analis CP707',
|
||||
},
|
||||
};
|
||||
|
||||
// We can run a small integration check by calling the router directly
|
||||
let resObj;
|
||||
await new Promise((resolve) => {
|
||||
const res = {
|
||||
statusCode: 200,
|
||||
headers: {},
|
||||
setHeader(name, val) {
|
||||
this.headers[name.toLowerCase()] = val;
|
||||
},
|
||||
status(code) {
|
||||
this.statusCode = code;
|
||||
return this;
|
||||
},
|
||||
json(data) {
|
||||
this.body = data;
|
||||
resObj = this;
|
||||
resolve();
|
||||
},
|
||||
};
|
||||
|
||||
app(req, res, (err) => {
|
||||
if (err) console.error('Router error:', err);
|
||||
resObj = res;
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
expect(resObj.statusCode).toBe(200);
|
||||
expect(resObj.body.success).toBe(true);
|
||||
expect(JSON.parse(resObj.body.response).headline).toBe('Analisis Test FCR');
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user