axonhub / integration_test /gemini /node /qa_simple.js
llzai's picture
Upload 1793 files
9853396 verified
const { GoogleGenAI } = require('@google/genai');
const { TestConfig } = require('./config');
// Test helper class
class TestHelper {
constructor() {
this.config = new TestConfig();
try {
this.config.validateConfig();
this.client = new GoogleGenAI({
apiKey: this.config.apiKey,
httpOptions:{
baseUrl: this.config.baseUrl,
headers: this.config.getHeaders()
}
});
} catch (error) {
console.log(`Skipping tests due to configuration error: ${error.message}`);
process.exit(0);
}
}
printHeaders() {
console.log(`Using headers: ${JSON.stringify(this.config.getHeaders())}`);
}
createTestContext() {
// In Node.js, we'll pass headers through request options
return {
headers: this.config.getHeaders()
};
}
assertNoError(error, message) {
if (error) {
throw new Error(`${message}: ${error.message}`);
}
}
validateChatResponse(response, description) {
if (!response) {
throw new Error(`Response is null for ${description}`);
}
if (!response.candidates || response.candidates.length === 0) {
throw new Error(`No candidates in response for ${description}`);
}
const candidate = response.candidates[0];
if (!candidate.content || !candidate.content.parts || candidate.content.parts.length === 0) {
throw new Error(`Empty content in response for ${description}`);
}
console.log(`${description} - Response validated successfully: ${response.candidates.length} candidates`);
}
getModel() {
return this.config.model;
}
}
// Utility functions
function containsCaseInsensitive(text, substring) {
return text.toLowerCase().includes(substring.toLowerCase());
}
function containsAnyCaseInsensitive(text, ...substrings) {
return substrings.some(substring => containsCaseInsensitive(text, substring));
}
function extractTextFromResponse(response) {
if (!response || !response.candidates || response.candidates.length === 0) {
return '';
}
const candidate = response.candidates[0];
if (!candidate.content || !candidate.content.parts || candidate.content.parts.length === 0) {
return '';
}
return candidate.content.parts
.filter(part => part.text)
.map(part => part.text)
.join('');
}
function containsNumber(text) {
const numbers = ['4', 'four', 'Four'];
return numbers.some(num => containsCaseInsensitive(text, num));
}
// Test functions
async function testSimpleQA() {
console.log('Running TestSimpleQA...');
const helper = new TestHelper();
helper.printHeaders();
const context = helper.createTestContext();
const question = 'What is 2 + 2?';
console.log(`Sending question: ${question}`);
const modelName = helper.getModel();
try {
const response = await helper.client.models.generateContent({
model: modelName,
contents: question,
...context
});
helper.validateChatResponse(response, 'Simple Q&A');
const responseText = extractTextFromResponse(response);
console.log(`Response: ${responseText}`);
if (!containsNumber(responseText)) {
throw new Error(`Expected response to contain a number, got: ${responseText}`);
}
console.log('✅ TestSimpleQA passed');
} catch (error) {
console.error('❌ TestSimpleQA failed:', error.message);
throw error;
}
}
async function testSimpleQAWithDifferentQuestion() {
console.log('Running TestSimpleQAWithDifferentQuestion...');
const helper = new TestHelper();
const context = helper.createTestContext();
const question = 'What is the capital of France?';
console.log(`Sending question: ${question}`);
const modelName = helper.getModel();
try {
const response = await helper.client.models.generateContent({
model: modelName,
contents: question,
...context
});
helper.validateChatResponse(response, 'Simple Q&A with capital question');
const responseText = extractTextFromResponse(response);
console.log(`Response: ${responseText}`);
if (!containsCaseInsensitive(responseText, 'Paris')) {
throw new Error(`Expected response to contain 'Paris', got: ${responseText}`);
}
console.log('✅ TestSimpleQAWithDifferentQuestion passed');
} catch (error) {
console.error('❌ TestSimpleQAWithDifferentQuestion failed:', error.message);
throw error;
}
}
async function testMultipleQuestions() {
console.log('Running TestMultipleQuestions...');
const helper = new TestHelper();
const context = helper.createTestContext();
const questions = [
'What is the largest planet in our solar system?',
'Who wrote Romeo and Juliet?',
'What is the chemical symbol for gold?'
];
const modelName = helper.getModel();
try {
for (let i = 0; i < questions.length; i++) {
const question = questions[i];
console.log(`Question ${i + 1}: ${question}`);
const response = await helper.client.models.generateContent({
model: modelName,
contents: question,
...context
});
helper.validateChatResponse(response, `Question ${i + 1}`);
const responseText = extractTextFromResponse(response);
console.log(`Answer ${i + 1}: ${responseText}`);
}
console.log('✅ TestMultipleQuestions passed');
} catch (error) {
console.error('❌ TestMultipleQuestions failed:', error.message);
throw error;
}
}
async function testConversationHistory() {
console.log('Running TestConversationHistory...');
const helper = new TestHelper();
const context = helper.createTestContext();
const modelName = helper.getModel();
try {
// Start a chat session
const chat = helper.client.chats.create({
model: modelName,
history: [],
config: {
temperature: 0.5
}
});
// First question
const question1 = "My name is Alice. What's your name?";
console.log(`Question 1: ${question1}`);
const response1 = await chat.sendMessage(question1);
helper.validateChatResponse(response1, 'First message');
const responseText1 = extractTextFromResponse(response1);
console.log(`Response 1: ${responseText1}`);
// Follow-up question that references the previous context
const question2 = 'What did I just tell you my name is?';
console.log(`Question 2: ${question2}`);
const response2 = await chat.sendMessage(question2);
helper.validateChatResponse(response2, 'Second message');
const responseText2 = extractTextFromResponse(response2);
console.log(`Response 2: ${responseText2}`);
// Verify the model remembers the name
if (!containsAnyCaseInsensitive(responseText2, 'Alice', 'alice')) {
throw new Error(`Expected response to contain 'Alice', got: ${responseText2}`);
}
console.log('✅ TestConversationHistory passed');
} catch (error) {
console.error('❌ TestConversationHistory failed:', error.message);
throw error;
}
}
// Main test runner
async function runTests() {
console.log('🚀 Starting Gemini Node.js Integration Tests\n');
const tests = [
testSimpleQA,
testSimpleQAWithDifferentQuestion,
testMultipleQuestions,
testConversationHistory
];
let passed = 0;
let failed = 0;
for (const test of tests) {
try {
await test();
passed++;
} catch (error) {
failed++;
console.error(`Test failed: ${error.message}`);
}
console.log(''); // Empty line for readability
}
console.log(`\n📊 Test Results: ${passed} passed, ${failed} failed`);
if (failed > 0) {
process.exit(1);
} else {
console.log('🎉 All tests passed!');
process.exit(0);
}
}
// Run tests if this file is executed directly
if (require.main === module) {
runTests().catch(error => {
console.error('❌ Test runner failed:', error.message);
process.exit(1);
});
}
module.exports = {
TestConfig,
TestHelper,
testSimpleQA,
testSimpleQAWithDifferentQuestion,
testMultipleQuestions,
testConversationHistory,
runTests
};