test-node-repl.js•4.77 kB
/**
* Specialized test for Node.js REPL interaction
* This test uses a direct approach with the child_process module
* to better understand and debug Node.js REPL behavior
*/
import { spawn } from 'child_process';
import fs from 'fs/promises';
import path from 'path';
import { fileURLToPath } from 'url';
// Get directory name
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// Colors for console output
const colors = {
reset: '\x1b[0m',
green: '\x1b[32m',
red: '\x1b[31m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
cyan: '\x1b[36m'
};
/**
* Sleep function
*/
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
/**
* Test Node.js REPL interaction directly
*/
async function testNodeREPL() {
console.log(`${colors.blue}Direct Node.js REPL test...${colors.reset}`);
// Create output directory if it doesn't exist
const OUTPUT_DIR = path.join(__dirname, 'test_output');
try {
await fs.mkdir(OUTPUT_DIR, { recursive: true });
} catch (error) {
console.warn(`${colors.yellow}Warning: Could not create output directory: ${error.message}${colors.reset}`);
}
// File for debugging output
const debugFile = path.join(OUTPUT_DIR, 'node_repl_debug.txt');
let debugLog = '';
// Log both to console and to file
function log(message) {
console.log(message);
debugLog += message + '\n';
}
// Start Node.js REPL
log(`${colors.blue}Starting Node.js REPL...${colors.reset}`);
// Use the -i flag to ensure interactive mode
const node = spawn('node', ['-i']);
// Track all output
let outputBuffer = '';
// Set up output listeners
node.stdout.on('data', (data) => {
const text = data.toString();
outputBuffer += text;
log(`${colors.green}[STDOUT] ${text.trim()}${colors.reset}`);
});
node.stderr.on('data', (data) => {
const text = data.toString();
outputBuffer += text;
log(`${colors.red}[STDERR] ${text.trim()}${colors.reset}`);
});
// Set up exit handler
node.on('exit', (code) => {
log(`${colors.blue}Node.js process exited with code ${code}${colors.reset}`);
// Write debug log to file after exit
fs.writeFile(debugFile, debugLog).catch(err => {
console.error(`Failed to write debug log: ${err.message}`);
});
});
// Wait for Node.js to initialize
log(`${colors.blue}Waiting for Node.js startup...${colors.reset}`);
await sleep(2000);
// Log initial state
log(`${colors.blue}Initial output buffer: ${outputBuffer}${colors.reset}`);
// Send a simple command
log(`${colors.blue}Sending simple command...${colors.reset}`);
node.stdin.write('console.log("Hello from Node.js!");\n');
// Wait for command to execute
await sleep(2000);
// Log state after first command
log(`${colors.blue}Output after first command: ${outputBuffer}${colors.reset}`);
// Send a multi-line command directly
log(`${colors.blue}Sending multi-line command directly...${colors.reset}`);
// Define the multi-line code
const multilineCode = `
function greet(name) {
return \`Hello, \${name}!\`;
}
for (let i = 0; i < 3; i++) {
console.log(greet(\`User \${i}\`));
}
`;
log(`${colors.blue}Sending code:${colors.reset}\n${multilineCode}`);
// Send the multi-line code directly
node.stdin.write(multilineCode + '\n');
// Wait for execution
await sleep(3000);
// Log final state
log(`${colors.blue}Final output buffer: ${outputBuffer}${colors.reset}`);
// Check if we got the expected output
const containsHello = outputBuffer.includes('Hello from Node.js!');
const containsGreetings =
outputBuffer.includes('Hello, User 0!') &&
outputBuffer.includes('Hello, User 1!') &&
outputBuffer.includes('Hello, User 2!');
log(`${colors.blue}Found "Hello from Node.js!": ${containsHello}${colors.reset}`);
log(`${colors.blue}Found greetings: ${containsGreetings}${colors.reset}`);
// Terminate the process
log(`${colors.blue}Terminating Node.js process...${colors.reset}`);
node.stdin.end();
// Wait for process to exit
await sleep(1000);
// Return success status
return containsHello && containsGreetings;
}
// Run the test
testNodeREPL()
.then(success => {
console.log(`\n${colors.blue}Direct Node.js REPL test ${success ? colors.green + 'PASSED' : colors.red + 'FAILED'}${colors.reset}`);
// Print file location for debug log
console.log(`${colors.blue}Debug log saved to: ${path.join(__dirname, 'test_output', 'node_repl_debug.txt')}${colors.reset}`);
process.exit(success ? 0 : 1);
})
.catch(error => {
console.error(`${colors.red}Test error: ${error.message}${colors.reset}`);
process.exit(1);
});