const { GoogleGenAI } = require("@google/genai"); const { TestConfig } = require("./config"); class StreamingTestHelper { 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); } } getModel() { return this.config.model; } createRequestContext() { return { headers: this.config.getHeaders(), }; } } async function collectStream(stream) { let fullText = ""; let chunkCount = 0; for await (const chunk of stream) { chunkCount++; if (!chunk || !chunk.candidates || chunk.candidates.length === 0) { continue; } const candidate = chunk.candidates[0]; const parts = candidate.content?.parts || []; for (const part of parts) { if (part?.text) { fullText += part.text; console.log(`Stream chunk ${chunkCount}: ${part.text}`); } } } return { fullText, chunkCount }; } async function testBasicStreamingChatCompletion() { console.log("Running TestBasicStreamingChatCompletion..."); const helper = new StreamingTestHelper(); const modelName = helper.getModel(); const context = helper.createRequestContext(); const question = "Tell me a short story about a robot learning to paint."; console.log(`Sending streaming request: ${question}`); try { const stream = await helper.client.models.generateContentStream({ model: modelName, contents: [ { role: "user", parts: [{ text: question }], }, ], ...context, }); const { fullText, chunkCount } = await collectStream(stream); console.log(`Total streaming responses: ${chunkCount}`); if (!fullText) { throw new Error("Expected non-empty streaming response"); } if ( !fullText.toLowerCase().includes("robot") && !fullText.toLowerCase().includes("paint") ) { throw new Error( `Expected content to mention robot or paint, got: ${fullText}` ); } console.log("✅ TestBasicStreamingChatCompletion passed"); } catch (error) { error.stack && console.error("❌ TestBasicStreamingChatCompletion failed:", error.stack); console.error("❌ TestBasicStreamingChatCompletion failed:", error.message); throw error; } } async function testLongResponseStreaming() { console.log("Running TestLongResponseStreaming..."); const helper = new StreamingTestHelper(); const modelName = helper.getModel(); const context = helper.createRequestContext(); const question = "Write a detailed explanation of how photosynthesis works, including the light-dependent and light-independent reactions."; console.log("Sending streaming request for long response..."); try { const stream = await helper.client.models.generateContentStream({ model: modelName, contents: [ { role: "user", parts: [{ text: question }], }, ], ...context, }); const { fullText, chunkCount } = await collectStream(stream); console.log( `Long streamed response: ${fullText.length} characters in ${chunkCount} chunks` ); if (fullText.length < 100) { throw new Error( `Expected longer content, got: ${fullText.length} characters` ); } const expectedTerms = [ "photosynthesis", "light", "chlorophyll", "carbon dioxide", "oxygen", ]; const foundTerms = expectedTerms.filter((term) => fullText.toLowerCase().includes(term) ); if (foundTerms.length < 2) { throw new Error( `Expected explanation to contain more key terms, found ${foundTerms.length}/${expectedTerms.length}` ); } console.log("✅ TestLongResponseStreaming passed"); } catch (error) { console.error("❌ TestLongResponseStreaming failed:", error.message); throw error; } } async function runStreamingTests() { console.log("🚀 Starting Gemini Node.js Streaming Tests\n"); const tests = [testBasicStreamingChatCompletion, testLongResponseStreaming]; 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(""); } console.log( `\n📊 Streaming Test Results: ${passed} passed, ${failed} failed` ); if (failed > 0) { process.exit(1); } else { console.log("🎉 All streaming tests passed!"); process.exit(0); } } if (require.main === module) { runStreamingTests().catch((error) => { console.error("❌ Streaming test runner failed:", error.message); process.exit(1); }); } module.exports = { StreamingTestHelper, testBasicStreamingChatCompletion, testLongResponseStreaming, runStreamingTests, };