ObsiViewer/server/integrations/gemini/gemini.health.service.spec.mjs
Bruno Charest 59d8a9f83a feat: add multi-select notes and Gemini AI integration
- Implemented multi-selection for notes with Ctrl+click, long-press, and keyboard shortcuts (Ctrl+A, Escape)
- Added Gemini API integration with environment configuration and routes
- Enhanced code block UI with improved copy feedback animation and visual polish
- Added sort order toggle (asc/desc) for note lists with persistent state
2025-11-04 09:54:03 -05:00

154 lines
4.9 KiB
JavaScript

import { describe, it, beforeEach, afterEach } from 'node:test';
import assert from 'node:assert';
import { GeminiHealthService } from './gemini.health.service.mjs';
describe('GeminiHealthService', () => {
let service;
let originalEnv;
beforeEach(() => {
// Sauvegarder l'environnement original
originalEnv = { ...process.env };
service = new GeminiHealthService();
});
afterEach(() => {
// Restaurer l'environnement
process.env = originalEnv;
});
describe('getStatus()', () => {
it('should return NOT_CONFIGURED when GEMINI_API_KEY is missing', () => {
delete process.env.GEMINI_API_KEY;
const status = service.getStatus();
assert.strictEqual(status.status, 'NOT_CONFIGURED');
assert.strictEqual(status.details.reason, 'missing_key');
assert.strictEqual(status.details.httpCode, null);
});
it('should return NOT_CONFIGURED when GEMINI_API_KEY is empty string', () => {
process.env.GEMINI_API_KEY = '';
const status = service.getStatus();
assert.strictEqual(status.status, 'NOT_CONFIGURED');
assert.strictEqual(status.details.reason, 'missing_key');
});
it('should return NOT_CONFIGURED when GEMINI_API_KEY is only whitespace', () => {
process.env.GEMINI_API_KEY = ' ';
const status = service.getStatus();
assert.strictEqual(status.status, 'NOT_CONFIGURED');
assert.strictEqual(status.details.reason, 'missing_key');
});
it('should return CONFIGURED_UNVERIFIED when key is present but never tested', () => {
process.env.GEMINI_API_KEY = 'test-key';
service.tested = false;
const status = service.getStatus();
assert.strictEqual(status.status, 'CONFIGURED_UNVERIFIED');
assert.strictEqual(status.details.reason, 'not_tested');
assert.strictEqual(status.details.httpCode, null);
});
it('should return cached status when already tested', () => {
process.env.GEMINI_API_KEY = 'test-key';
service.tested = true;
service.cache = {
status: 'WORKING',
lastCheckedAt: '2025-01-01T00:00:00.000Z',
details: { reason: 'ok', httpCode: 200 }
};
const status = service.getStatus();
assert.strictEqual(status.status, 'WORKING');
assert.strictEqual(status.details.reason, 'ok');
assert.strictEqual(status.details.httpCode, 200);
});
});
describe('canRunTest()', () => {
it('should allow test on first call', () => {
const result = service.canRunTest('127.0.0.1');
assert.strictEqual(result.allowed, true);
});
it('should block test if called too soon', () => {
const clientIp = '127.0.0.1';
service.lastTestByIp.set(clientIp, Date.now());
const result = service.canRunTest(clientIp);
assert.strictEqual(result.allowed, false);
assert.strictEqual(result.reason, 'rate_limited');
assert.ok(result.waitSeconds > 0);
});
it('should allow test after minimum interval', (t, done) => {
const clientIp = '127.0.0.1';
// Simuler un test ancien (31 secondes)
service.lastTestByIp.set(clientIp, Date.now() - 31000);
const result = service.canRunTest(clientIp);
assert.strictEqual(result.allowed, true);
done();
});
});
describe('reset()', () => {
it('should reset all state to initial values', () => {
// Modifier l'état
service.tested = true;
service.cache = {
status: 'WORKING',
lastCheckedAt: '2025-01-01T00:00:00.000Z',
details: { reason: 'ok', httpCode: 200 }
};
service.lastTestByIp.set('127.0.0.1', Date.now());
// Reset
service.reset();
// Vérifier
assert.strictEqual(service.tested, false);
assert.strictEqual(service.cache.status, 'CONFIGURED_UNVERIFIED');
assert.strictEqual(service.cache.lastCheckedAt, null);
assert.strictEqual(service.cache.details.reason, 'not_tested');
assert.strictEqual(service.lastTestByIp.size, 0);
});
});
describe('runLiveTest() - edge cases', () => {
it('should return NOT_CONFIGURED if key is missing', async () => {
delete process.env.GEMINI_API_KEY;
const result = await service.runLiveTest('127.0.0.1');
assert.strictEqual(result.status, 'NOT_CONFIGURED');
assert.strictEqual(result.details.reason, 'missing_key');
assert.strictEqual(service.tested, false);
});
it('should respect rate limiting', async () => {
process.env.GEMINI_API_KEY = 'test-key';
service.lastTestByIp.set('127.0.0.1', Date.now());
service.cache = {
status: 'WORKING',
lastCheckedAt: '2025-01-01T00:00:00.000Z',
details: { reason: 'ok', httpCode: 200 }
};
const result = await service.runLiveTest('127.0.0.1');
assert.strictEqual(result.details.reason, 'rate_limited');
assert.ok(result.details.waitSeconds);
});
});
});