From 9698761b2b60f4b3354e3e5b3072bc42d3adb435 Mon Sep 17 00:00:00 2001 From: jelveh Date: Fri, 4 Jul 2025 19:01:16 -0700 Subject: [PATCH] AND MOOOAREEE AI tests --- src/puter-js/test/ai.test.js | 267 +++++++++++++++++------------------ src/puter-js/test/run.html | 12 ++ 2 files changed, 145 insertions(+), 134 deletions(-) diff --git a/src/puter-js/test/ai.test.js b/src/puter-js/test/ai.test.js index 933ff2949..83aace653 100644 --- a/src/puter-js/test/ai.test.js +++ b/src/puter-js/test/ai.test.js @@ -1,141 +1,140 @@ /* eslint-disable */ // TODO: Make these more compatible with eslint -window.aiTests = [ - testChatBasicPrompt = async function() { - try { - // Test basic string prompt with test mode enabled - const result = await puter.ai.chat("Hello, how are you?", { model: "openrouter:openai/gpt-4.1-mini" }); - - // Check that result is an object and not null - assert(typeof result === 'object', "chat should return an object"); - assert(result !== null, "chat should not return null"); - - console.log('result', result); - // Check response structure - assert(typeof result.index === 'number', "result should have index number"); - assert(typeof result.message === 'object', "result should have message object"); - assert(typeof result.finish_reason === 'string', "result should have finish_reason string"); - assert(result.hasOwnProperty('logprobs'), "result should have logprobs property"); - assert(typeof result.via_ai_chat_service === 'boolean', "result should have via_ai_chat_service boolean"); - - // Check message structure - assert(typeof result.message.role === 'string', "message should have role string"); - assert(result.message.role === 'assistant', "message role should be 'assistant'"); - assert(typeof result.message.content === 'string', "message should have content string"); - assert(result.message.hasOwnProperty('refusal'), "message should have refusal property"); - // Check usage tracking - if (result.usage) { - assert(Array.isArray(result.usage), "usage should be an array"); - result.usage.forEach(usage => { - assert(typeof usage.type === 'string', "usage should have type string"); - assert(typeof usage.model === 'string', "usage should have model string"); - assert(typeof usage.amount === 'number', "usage should have amount number"); - assert(typeof usage.cost === 'number', "usage should have cost number"); - }); +// Define models to test +const TEST_MODELS = [ + "openrouter:openai/gpt-4.1-mini", + "openrouter:anthropic/claude-3.5-sonnet-20240620", + "gpt-4o-mini", + "claude-sonnet-4-latest", + // Add more models as needed +]; + +// Core test functions that can be reused across models +const testChatBasicPromptCore = async function(model) { + // Test basic string prompt with test mode enabled + const result = await puter.ai.chat("Hello, how are you?", { model: model }); + + // Check that result is an object and not null + assert(typeof result === 'object', "chat should return an object"); + assert(result !== null, "chat should not return null"); + + // Check response structure + assert(typeof result.message === 'object', "result should have message object"); + assert(typeof result.finish_reason === 'string', "result should have finish_reason string"); + assert(typeof result.via_ai_chat_service === 'boolean', "result should have via_ai_chat_service boolean"); + + // Check message structure + assert(typeof result.message.role === 'string', "message should have role string"); + assert(result.message.role === 'assistant', "message role should be 'assistant'"); + assert(typeof result.message.content === 'string' || Array.isArray(result.message.content), "message should have content string or an array"); + + // Check that toString() and valueOf() methods exist and work + assert(typeof result.toString === 'function', "result should have toString method"); + assert(typeof result.valueOf === 'function', "result should have valueOf method"); + + // Check that toString() and valueOf() return the message content + assert(result.toString() === result.message.content, "toString() should return message content"); + assert(result.valueOf() === result.message.content, "valueOf() should return message content"); + + // Content should not be empty + assert(result.message.content.length > 0, "message content should not be empty"); +}; + +const testChatWithParametersCore = async function(model) { + // Test chat with parameters object + const result = await puter.ai.chat("What is 2+2?", { + model: model, + temperature: 0.7, + max_tokens: 50 + }); + + // Check basic result structure + assert(typeof result === 'object', "chat should return an object"); + assert(result !== null, "chat should not return null"); + assert(typeof result.message === 'object', "result should have message object"); + assert(typeof result.message.content === 'string' || Array.isArray(result.message.content), "result.message should have content string or an array"); + + // Check that the methods work + assert(typeof result.toString === 'function', "result should have toString method"); + assert(typeof result.valueOf === 'function', "result should have valueOf method"); + + // Check that finish_reason is present and valid + const validFinishReasons = ['stop', 'length', 'function_call', 'content_filter', 'tool_calls']; + assert(validFinishReasons.includes(result.finish_reason), + `finish_reason should be one of: ${validFinishReasons.join(', ')}`); + + // Check that via_ai_chat_service is true + assert(result.via_ai_chat_service === true, "via_ai_chat_service should be true"); +}; + +const testChatWithMessageArrayCore = async function(model) { + // Test chat with message array format + const messages = [ + { role: "system", content: "You are a helpful assistant." }, + { role: "user", content: "Hello!" } + ]; + const result = await puter.ai.chat(messages, { model: model }); + + // Check basic structure + assert(typeof result === 'object', "chat should return an object"); + assert(typeof result.message === 'object', "result should have message object"); + assert(result.message.role === 'assistant', "response should be from assistant"); + + // Check that content is present and not empty + assert(result.message.content.length > 0, "message content should not be empty"); + + // Check that index is 0 (first/only response) + assert(result.index === 0, "index should be 0 for single response"); +}; + +// Function to generate test functions for a specific model +const generateTestsForModel = function(model) { + const modelName = model.replace(/[^a-zA-Z0-9]/g, '_'); // Sanitize model name for function names + + return { + [`testChatBasicPrompt_${modelName}`]: async function() { + try { + await testChatBasicPromptCore(model); + pass(`testChatBasicPrompt_${modelName} passed`); + } catch (error) { + fail(`testChatBasicPrompt_${modelName} failed:`, error); } - - // Check that toString() and valueOf() methods exist and work - assert(typeof result.toString === 'function', "result should have toString method"); - assert(typeof result.valueOf === 'function', "result should have valueOf method"); - - // Check that toString() and valueOf() return the message content - assert(result.toString() === result.message.content, "toString() should return message content"); - assert(result.valueOf() === result.message.content, "valueOf() should return message content"); - - // Content should not be empty - assert(result.message.content.length > 0, "message content should not be empty"); - - pass("testChatBasicPrompt passed"); - } catch (error) { - fail("testChatBasicPrompt failed:", error); - } - }, + }, + + [`testChatWithParameters_${modelName}`]: async function() { + try { + await testChatWithParametersCore(model); + pass(`testChatWithParameters_${modelName} passed`); + } catch (error) { + fail(`testChatWithParameters_${modelName} failed:`, error); + } + }, + + [`testChatWithMessageArray_${modelName}`]: async function() { + try { + await testChatWithMessageArrayCore(model); + pass(`testChatWithMessageArray_${modelName} passed`); + } catch (error) { + fail(`testChatWithMessageArray_${modelName} failed:`, error); + } + }, + }; +}; - testChatWithParameters = async function() { - try { - // Test chat with parameters object - const result = await puter.ai.chat("What is 2+2?", { - model: "openrouter:openai/gpt-4.1-mini", - temperature: 0.7, - max_tokens: 50 - }); - - // Check basic result structure - assert(typeof result === 'object', "chat should return an object"); - assert(result !== null, "chat should not return null"); - assert(typeof result.message === 'object', "result should have message object"); - assert(typeof result.message.content === 'string', "result.message should have content string"); - - // Check that the methods work - assert(typeof result.toString === 'function', "result should have toString method"); - assert(typeof result.valueOf === 'function', "result should have valueOf method"); - - // Check that finish_reason is present and valid - const validFinishReasons = ['stop', 'length', 'function_call', 'content_filter', 'tool_calls']; - assert(validFinishReasons.includes(result.finish_reason), - `finish_reason should be one of: ${validFinishReasons.join(', ')}`); - - // Check that via_ai_chat_service is true - assert(result.via_ai_chat_service === true, "via_ai_chat_service should be true"); - - pass("testChatWithParameters passed"); - } catch (error) { - fail("testChatWithParameters failed:", error); - } - }, +// Generate all test functions for all models +const generateAllTests = function() { + const allTests = []; - testChatWithMessageArray = async function() { - try { - // Test chat with message array format - const messages = [ - { role: "system", content: "You are a helpful assistant." }, - { role: "user", content: "Hello!" } - ]; - const result = await puter.ai.chat(messages); - - // Check basic structure - assert(typeof result === 'object', "chat should return an object"); - assert(typeof result.message === 'object', "result should have message object"); - assert(result.message.role === 'assistant', "response should be from assistant"); - - // Check that content is present and not empty - assert(result.message.content.length > 0, "message content should not be empty"); - - // Check that index is 0 (first/only response) - assert(result.index === 0, "index should be 0 for single response"); - - pass("testChatWithMessageArray passed"); - } catch (error) { - fail("testChatWithMessageArray failed:", error); - } - }, + TEST_MODELS.forEach(model => { + const modelTests = generateTestsForModel(model); + Object.values(modelTests).forEach(testFunc => { + allTests.push(testFunc); + }); + }); - testChatUsageTracking = async function() { - try { - // Test that usage tracking works correctly - const result = await puter.ai.chat("Count to 5"); - - // Check usage tracking exists - assert(result.usage, "result should have usage tracking"); - assert(Array.isArray(result.usage), "usage should be an array"); - assert(result.usage.length > 0, "usage array should not be empty"); - - // Check for both prompt and completion usage - const usageTypes = result.usage.map(u => u.type); - assert(usageTypes.includes('prompt'), "usage should include prompt tracking"); - assert(usageTypes.includes('completion'), "usage should include completion tracking"); - - // Check that costs are calculated - result.usage.forEach(usage => { - assert(usage.amount > 0, "usage amount should be greater than 0"); - assert(usage.cost >= 0, "usage cost should be non-negative"); - assert(typeof usage.model === 'string', "usage should track model used"); - }); - - pass("testChatUsageTracking passed"); - } catch (error) { - fail("testChatUsageTracking failed:", error); - } - }, -]; \ No newline at end of file + return allTests; +}; + +// Export the generated tests +window.aiTests = generateAllTests(); \ No newline at end of file diff --git a/src/puter-js/test/run.html b/src/puter-js/test/run.html index 0dae66f10..3793279ea 100644 --- a/src/puter-js/test/run.html +++ b/src/puter-js/test/run.html @@ -35,6 +35,18 @@ padding: 10px; border-radius: 5px; } + .test-container{ + font-family: monospace; + } + .test-container:hover{ + background-color: #f0f0f0; + } + .test-container label{ + display: block; + } + .test-container input{ + float: left; + }