#!/usr/bin/env node /** * Comprehensive Test Script for @soulcraft/brainy * * This script tests the library in all environments: * - Browser (using Puppeteer for headless browser testing) * - Node.js/server * - CLI * * It verifies: * - Library loading in each environment * - TensorFlow functionality in each environment * - Environment detection functionality */ import { execSync } from 'child_process' import { fileURLToPath } from 'url' import path from 'path' import fs from 'fs' import http from 'http' import puppeteer from 'puppeteer' // Get the directory of the current module const __filename = fileURLToPath(import.meta.url) const __dirname = path.dirname(__filename) const rootDir = path.join(__dirname, '..') // Define colors for console output const colors = { reset: '\x1b[0m', bright: '\x1b[1m', green: '\x1b[32m', yellow: '\x1b[33m', red: '\x1b[31m', cyan: '\x1b[36m', magenta: '\x1b[35m', blue: '\x1b[34m' } // Helper function to log with colors function log(message, color = colors.reset) { console.log(`${color}${message}${colors.reset}`) } // Helper function to log section headers function logSection(title) { console.log('\n' + '='.repeat(80)) console.log(`${colors.bright}${colors.cyan}${title}${colors.reset}`) console.log('='.repeat(80) + '\n') } // Helper function to log subsection headers function logSubSection(title) { console.log('\n' + '-'.repeat(60)) console.log(`${colors.bright}${colors.magenta}${title}${colors.reset}`) console.log('-'.repeat(60) + '\n') } // Helper function to run a command and return its output function runCommand(command, cwd = rootDir) { try { return execSync(command, { stdio: 'pipe', cwd, encoding: 'utf8' }) } catch (error) { log(`Error running command: ${command}`, colors.red) log(error.message, colors.red) if (error.stdout) log(`stdout: ${error.stdout}`) if (error.stderr) log(`stderr: ${error.stderr}`, colors.red) throw error } } // Create a simple HTML file for browser testing function createBrowserTestFile() { const testHtmlPath = path.join(rootDir, 'browser-test.html') const htmlContent = ` @soulcraft/brainy Browser Test

@soulcraft/brainy Browser Test

This page tests the @soulcraft/brainy library in a browser environment.

Test results will appear here...
`; fs.writeFileSync(testHtmlPath, htmlContent); return testHtmlPath; } // Create a Node.js test script function createNodeTestScript() { const testScriptPath = path.join(rootDir, 'node-test.js'); const scriptContent = ` // Node.js test script for @soulcraft/brainy // CRITICAL: First, directly apply the TensorFlow.js patch // This is the most reliable way to ensure the patch is applied before TensorFlow.js is loaded import { TextEncoder, TextDecoder } from 'util'; // Make TextEncoder and TextDecoder available globally if (typeof global !== 'undefined') { global.TextEncoder = TextEncoder; global.TextDecoder = TextDecoder; } // Import the library import * as brainy from './dist/unified.js'; async function runNodeTest() { console.log('\\n=== Testing @soulcraft/brainy in Node.js environment ===\\n'); try { // Test environment detection console.log('Environment Detection:'); console.log(\`- isBrowser: \${brainy.isBrowser()}\`); console.log(\`- isNode: \${brainy.isNode()}\`); console.log(\`- isWebWorker: \${brainy.isWebWorker()}\`); console.log(\`- areWebWorkersAvailable: \${brainy.areWebWorkersAvailable()}\`); console.log(\`- isThreadingAvailable: \${brainy.isThreadingAvailable()}\`); console.log(\`- areWorkerThreadsAvailableSync: \${brainy.areWorkerThreadsAvailableSync()}\`); // Test TensorFlow functionality console.log('\\nTesting TensorFlow functionality...'); // Create a simple BrainyData instance const data = new brainy.BrainyData({ dimensions: 2, metric: 'euclidean' }); console.log('Successfully created BrainyData instance'); // Initialize the database console.log('Initializing database...'); await data.init(); // Add a simple vector await data.add([1, 2], { id: 'test1', text: 'Test item' }); console.log('Successfully added item to BrainyData'); // Search for similar vectors const results = await data.search([1, 2], 1); console.log('Search results:', results); // Test embedding functionality (which uses TensorFlow) console.log('\\nTesting embedding functionality...'); const embeddingFunction = brainy.createEmbeddingFunction(); const embedding = await embeddingFunction('This is a test sentence'); console.log(\`Successfully created embedding with length: \${embedding.length}\`); console.log('\\n✅ All Node.js tests passed successfully!'); return true; } catch (error) { console.error('❌ Node.js test failed:', error); return false; } } // Run the test runNodeTest().then(success => { if (!success) { process.exit(1); } }); `; fs.writeFileSync(testScriptPath, scriptContent); return testScriptPath; } // Create a CLI test script function createCliTestScript() { const cliTestScriptPath = path.join(rootDir, 'cli-test.js'); const scriptContent = ` // CLI test script for @soulcraft/brainy-cli import { execSync } from 'child_process'; function runCommand(command) { try { return execSync(command, { stdio: 'pipe', encoding: 'utf8' }); } catch (error) { console.error(\`Error running command: \${command}\`); console.error(error.message); if (error.stdout) console.log(\`stdout: \${error.stdout}\`); if (error.stderr) console.error(\`stderr: \${error.stderr}\`); throw error; } } async function testCli() { console.log('\\n=== Testing @soulcraft/brainy-cli ===\\n'); try { // Test CLI version console.log('Testing CLI version...'); const versionOutput = runCommand('brainy --version'); console.log(\`CLI version: \${versionOutput.trim()}\`); // Test CLI help console.log('\\nTesting CLI help...'); runCommand('brainy --help'); console.log('Help command executed successfully'); // Test pipeline command console.log('\\nTesting pipeline command...'); const pipelineOutput = runCommand('brainy test-pipeline "This is a test"'); console.log('Pipeline test completed successfully'); // Test TensorFlow functionality in CLI console.log('\\nTesting TensorFlow functionality in CLI...'); const tensorflowOutput = runCommand('brainy test-tensorflow'); console.log('TensorFlow test completed successfully'); console.log('\\n✅ All CLI tests passed successfully!'); return true; } catch (error) { console.error('❌ CLI test failed. This might be expected if you don\\'t have the CLI installed globally.'); console.error('You can install the CLI globally with: npm run test:cli'); return false; } } // Run the test testCli().catch(error => { console.error('Unhandled error:', error); }); `; fs.writeFileSync(cliTestScriptPath, scriptContent); return cliTestScriptPath; } // Main function to run all tests async function runComprehensiveTests() { try { logSection('COMPREHENSIVE TEST SUITE FOR @soulcraft/brainy'); log('This test suite verifies the library in all environments: Browser, Node.js, and CLI', colors.yellow); logSection('BUILDING PACKAGES'); // Build the main package logSubSection('Building Main Package'); log('Building main package...', colors.yellow); runCommand('npm run build'); log('Main package built successfully!', colors.green); // Build the browser package logSubSection('Building Browser Package'); log('Building browser package...', colors.yellow); runCommand('npm run build:browser'); log('Browser package built successfully!', colors.green); // Build the CLI package logSubSection('Building CLI Package'); log('Building CLI package...', colors.yellow); runCommand('npm run build:cli'); log('CLI package built successfully!', colors.green); logSection('NODE.JS ENVIRONMENT TESTS'); // Create and run Node.js test script logSubSection('Creating Node.js Test Script'); const nodeTestScript = createNodeTestScript(); log(`Node.js test script created at: ${nodeTestScript}`, colors.green); logSubSection('Running Node.js Tests'); try { const nodeTestResult = runCommand(`node ${nodeTestScript}`); log(nodeTestResult); log('Node.js tests completed successfully!', colors.green); } catch (error) { log('Node.js tests failed!', colors.red); throw error; } logSection('BROWSER ENVIRONMENT TESTS'); // Create browser test file logSubSection('Creating Browser Test File'); const browserTestFile = createBrowserTestFile(); log(`Browser test file created at: ${browserTestFile}`, colors.green); // Start a simple HTTP server to serve the test files logSubSection('Starting HTTP Server'); const server = http.createServer((req, res) => { // Normalize the URL to handle relative paths const normalizedUrl = req.url.replace(/^\/+/, '/'); let filePath = path.join( rootDir, normalizedUrl === '/' ? 'browser-test.html' : normalizedUrl ); // Handle relative paths (e.g., ../dist/unified.js) if (normalizedUrl.includes('../')) { // Convert the URL to an absolute path relative to the root directory const parts = normalizedUrl.split('/'); const resolvedParts = []; for (const part of parts) { if (part === '..') { resolvedParts.pop(); } else if (part && part !== '.') { resolvedParts.push(part); } } filePath = path.join(rootDir, resolvedParts.join('/')); } log(`Request for: ${req.url}, resolved to: ${filePath}`, colors.blue); // Check if the file exists if (fs.existsSync(filePath)) { const extname = path.extname(filePath); let contentType = 'text/html'; switch (extname) { case '.js': contentType = 'text/javascript'; break; case '.css': contentType = 'text/css'; break; case '.json': contentType = 'application/json'; break; case '.png': contentType = 'image/png'; break; case '.jpg': contentType = 'image/jpg'; break; } res.writeHead(200, { 'Content-Type': contentType }); const fileStream = fs.createReadStream(filePath); fileStream.pipe(res); } else { log(`File not found: ${filePath}`, colors.red); res.writeHead(404); res.end('File not found'); } }); // Start the server on a random port const PORT = 3000 + Math.floor(Math.random() * 1000); server.listen(PORT); log(`HTTP server started on port ${PORT}`, colors.green); // Run browser tests using Puppeteer logSubSection('Running Browser Tests with Puppeteer'); log('Launching headless browser...', colors.yellow); const browser = await puppeteer.launch({ args: ['--no-sandbox'] }); const page = await browser.newPage(); // Capture console logs from the page page.on('console', (message) => { const type = message.type(); const text = message.text(); if (type === 'error') { log(`Browser console error: ${text}`, colors.red); } else { log(`Browser console: ${text}`, colors.blue); } }); // Navigate to the test page log('Navigating to browser test page...', colors.yellow); await page.goto(`http://localhost:${PORT}/browser-test.html`); // Run the test log('Running browser tests...', colors.yellow); await page.waitForSelector('#runTest'); await page.click('#runTest'); // Wait for test completion await page.waitForFunction( () => { const resultText = document.getElementById('result').textContent; return resultText.includes('All tests passed') || resultText.includes('Test failed'); }, { timeout: 60000 } ); // Get test results const browserTestResult = await page.evaluate(() => { return document.getElementById('result').innerHTML; }); log('Browser test results:', colors.green); log(browserTestResult.replace(/<[^>]*>/g, '').trim()); // Check if the test passed const browserTestPassed = browserTestResult.includes('All tests passed'); if (!browserTestPassed) { throw new Error('Browser tests failed!'); } // Close the browser and server await browser.close(); server.close(); log('HTTP server stopped', colors.green); logSection('CLI ENVIRONMENT TESTS'); // Create and run CLI test script logSubSection('Creating CLI Test Script'); const cliTestScript = createCliTestScript(); log(`CLI test script created at: ${cliTestScript}`, colors.green); logSubSection('Installing CLI Package Locally'); log('Installing CLI package locally for testing...', colors.yellow); try { runCommand('npm run test:cli'); log('CLI package installed successfully!', colors.green); logSubSection('Running CLI Tests'); try { const cliTestResult = runCommand(`node ${cliTestScript}`); log(cliTestResult); log('CLI tests completed!', colors.green); } catch (error) { log('CLI tests failed. This might be expected if you don\'t have the CLI installed globally.', colors.yellow); log('You can install the CLI globally with: npm run test:cli', colors.yellow); } } catch (error) { log('Failed to install CLI package locally. Skipping CLI tests.', colors.yellow); log('You can run the CLI tests separately with: npm run test:cli', colors.yellow); } logSection('CLEANING UP'); // Clean up test files log('Cleaning up test files...', colors.yellow); fs.unlinkSync(nodeTestScript); fs.unlinkSync(browserTestFile); fs.unlinkSync(cliTestScript); log('Test files removed', colors.green); logSection('TEST SUMMARY'); log('✅ All environment tests completed successfully!', colors.green); log('The library has been tested in the following environments:', colors.green); log('- Browser environment', colors.green); log('- Node.js/server environment', colors.green); log('- CLI environment', colors.green); log('\nTensorFlow functionality has been verified in all environments.', colors.green); log('Environment detection has been tested and is working correctly.', colors.green); } catch (error) { logSection('TEST FAILURE'); log(`Tests failed: ${error.message}`, colors.red); process.exit(1); } } // Run the tests runComprehensiveTests().catch((error) => { log(`Unhandled error: ${error.message}`, colors.red); process.exit(1); });