brainy/scripts/test-all-environments.js

301 lines
9.8 KiB
JavaScript
Raw Normal View History

#!/usr/bin/env node
/**
* Test All Environments
*
* This script runs tests for the Brainy library in all environments:
* - Browser (using Puppeteer for headless browser testing)
* - Node.js
* - CLI
*/
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'
}
// 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 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
}
}
// Main function to run all tests
async function runAllTests() {
try {
logSection('BUILDING PACKAGES')
// Build the main package
log('Building main package...', colors.yellow)
runCommand('npm run build')
log('Main package built successfully!', colors.green)
// Apply TextEncoder patch
log('Applying TextEncoder patch...', colors.yellow)
runCommand('node scripts/patch-textencoder.js')
log('TextEncoder patch applied successfully!', colors.green)
// Build the browser package
log('Building browser package...', colors.yellow)
runCommand('npm run build:browser')
log('Browser package built successfully!', colors.green)
// Build the CLI package
log('Building CLI package...', colors.yellow)
runCommand('npm run build:cli')
log('CLI package built successfully!', colors.green)
logSection('RUNNING NODE.JS TESTS')
// Run Node.js tests
log('Running Node.js worker test...', colors.yellow)
const nodeWorkerResult = runCommand('node test-worker.js')
log(nodeWorkerResult)
log('Node.js worker test completed!', colors.green)
log('Running unified text encoding test...', colors.yellow)
const textEncodingResult = runCommand('node test-unified-encoding.js')
log(textEncodingResult)
log('Unified text encoding test completed!', colors.green)
log('Running TensorFlow and TextEncoder test...', colors.yellow)
const tensorflowTextEncoderResult = runCommand('node test-tensorflow-textencoder.js')
log(tensorflowTextEncoderResult)
log('TensorFlow and TextEncoder test completed!', colors.green)
logSection('RUNNING BROWSER TESTS')
// Start a simple HTTP server to serve the test files
log('Starting HTTP server...', colors.yellow)
const server = http.createServer((req, res) => {
// Normalize the URL to handle relative paths
const normalizedUrl = req.url.replace(/^\/+/, '/')
let filePath = path.join(
rootDir,
normalizedUrl === '/' ? 'index.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.yellow)
// 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
log('Launching headless browser...', colors.yellow)
// Using --no-sandbox flag to avoid issues with the Chrome sandbox in certain environments
// See: https://chromium.googlesource.com/chromium/src/+/main/docs/linux/suid_sandbox_development.md
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}`)
}
})
// Test browser worker
log('Running browser worker test...', colors.yellow)
await page.goto(`http://localhost:${PORT}/demo/test-browser-worker.html`)
await page.waitForSelector('#runTest')
await page.click('#runTest')
await page.waitForFunction(
() => {
const resultText = document.getElementById('result').textContent
return resultText.includes('Worker thread execution completed')
},
{ timeout: 30000 }
)
const browserWorkerResult = await page.evaluate(() => {
return document.getElementById('result').innerHTML
})
log('Browser worker test result:', colors.green)
log(browserWorkerResult.replace(/<[^>]*>/g, '').trim())
// Test fallback mechanism
log('Running fallback test...', colors.yellow)
await page.goto(`http://localhost:${PORT}/demo/test-fallback.html`)
await page.waitForSelector('#runTest')
await page.click('#runTest')
await page.waitForFunction(
() => {
const resultText = document.getElementById('result').textContent
return resultText.includes('Test completed')
},
{ timeout: 30000 }
)
const fallbackResult = await page.evaluate(() => {
return document.getElementById('result').innerHTML
})
log('Fallback test result:', colors.green)
log(fallbackResult.replace(/<[^>]*>/g, '').trim())
// Test TensorFlow and TextEncoder in browser
log('Running TensorFlow and TextEncoder browser test...', colors.yellow)
await page.goto(`http://localhost:${PORT}/demo/test-tensorflow-textencoder.html`)
await page.waitForSelector('#runTest')
await page.click('#runTest')
await page.waitForFunction(
() => {
const resultText = document.getElementById('result').textContent
return resultText.includes('Test completed')
},
{ timeout: 30000 }
)
const browserTensorflowTextEncoderResult = await page.evaluate(() => {
return document.getElementById('result').innerHTML
})
log('TensorFlow and TextEncoder browser test result:', colors.green)
log(browserTensorflowTextEncoderResult.replace(/<[^>]*>/g, '').trim())
// Close the browser and server
await browser.close()
server.close()
log('HTTP server stopped', colors.green)
logSection('RUNNING CLI TESTS')
// Run CLI tests
log('Testing CLI package locally...', colors.yellow)
try {
runCommand('npm run test:cli')
log('CLI test completed!', colors.green)
// Run some basic CLI commands to verify functionality
log('Testing basic CLI commands...', colors.yellow)
const cliVersionResult = runCommand('brainy --version')
log(`CLI version: ${cliVersionResult.trim()}`, colors.green)
const cliHelpResult = runCommand('brainy --help')
log('CLI help command executed successfully', colors.green)
// Test the pipeline command
log('Testing pipeline command...', colors.yellow)
const pipelineResult = runCommand('brainy test-pipeline "This is a test"')
log('Pipeline test completed!', colors.green)
// Test TensorFlow and TextEncoder in CLI
log('Testing TensorFlow and TextEncoder in CLI...', colors.yellow)
const cliTensorflowResult = runCommand('brainy test-tensorflow-textencoder')
log('TensorFlow and TextEncoder CLI test 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 run the CLI tests separately with: npm run test:cli',
colors.yellow
)
}
logSection('ALL TESTS COMPLETED')
log('All environment tests completed successfully!', colors.green)
} catch (error) {
logSection('TEST FAILURE')
log(`Tests failed: ${error.message}`, colors.red)
process.exit(1)
}
}
// Run the tests
runAllTests().catch((error) => {
log(`Unhandled error: ${error.message}`, colors.red)
process.exit(1)
})