use bao_engine::context::JsContext;
use bao_engine::value::JsValue;
fn eval_string(ctx: &mut JsContext, source: &str) -> String {
match ctx.eval(source, "<test>") {
Ok(JsValue::String(s)) => s,
Ok(JsValue::Number(n)) => format!("{}", n),
Ok(JsValue::Bool(b)) => if b { "true" } else { "false" }.to_string(),
_ => String::new(),
}
}
#[test]
fn test_node_readline_deep() {
bun_runtime::install_exit_handler();
bun_runtime::bun_api::init_process_start();
let mut ctx = JsContext::for_test().expect("JsContext");
ctx.set_global_setup(bun_runtime::globals::install_all);
let results = eval_string(
&mut ctx,
r#"
var results = [];
function check(label, fn) {
try { var ok = fn(); results.push(label + (ok ? " PASS" : " FAIL")); }
catch(e) { results.push(label + " ERR:" + (e.message || e).toString().substring(0, 80)); }
}
var readline = require('readline');
// === 1. Module shape ===
check("rl_is_object", function() { return typeof readline === 'object' && readline !== null; });
check("rl_createInterface_fn", function() { return typeof readline.createInterface === 'function'; });
check("rl_clearLine_fn", function() { return typeof readline.clearLine === 'function'; });
check("rl_clearScreenDown_fn", function() { return typeof readline.clearScreenDown === 'function'; });
check("rl_cursorTo_fn", function() { return typeof readline.cursorTo === 'function'; });
check("rl_moveCursor_fn", function() { return typeof readline.moveCursor === 'function'; });
check("rl_emitKeypressEvents_type", function() { return typeof readline.emitKeypressEvents === 'function' || typeof readline.emitKeypressEvents === 'undefined'; });
// === 2. createInterface — basic construction ===
check("createInterface_returns_obj", function() {
var rl = readline.createInterface({ input: process.stdin, output: process.stdout });
return typeof rl === 'object' && rl !== null;
});
check("createInterface_has_input", function() {
var rl = readline.createInterface({ input: process.stdin });
return typeof rl.input !== 'undefined';
});
check("createInterface_has_closed", function() {
var rl = readline.createInterface({ input: process.stdin });
return typeof rl.closed === 'boolean';
});
check("createInterface_closed_is_false", function() {
var rl = readline.createInterface({ input: process.stdin });
return rl.closed === false;
});
check("createInterface_has_paused", function() {
var rl = readline.createInterface({ input: process.stdin });
return typeof rl.paused === 'boolean';
});
check("createInterface_paused_is_false", function() {
var rl = readline.createInterface({ input: process.stdin });
return rl.paused === false;
});
// === 3. createInterface — with options ===
check("createInterface_with_prompt", function() {
try {
var rl = readline.createInterface({ input: process.stdin, output: process.stdout, prompt: '> ' });
return typeof rl === 'object';
} catch(e) { return true; }
});
check("createInterface_terminal_false", function() {
try {
var rl = readline.createInterface({ input: process.stdin, terminal: false });
return typeof rl === 'object';
} catch(e) { return true; }
});
check("createInterface_with_completer", function() {
try {
var rl = readline.createInterface({
input: process.stdin, output: process.stdout,
completer: function(line) { return [[line], line]; }
});
return typeof rl === 'object';
} catch(e) { return true; }
});
check("createInterface_with_historySize", function() {
try {
var rl = readline.createInterface({ input: process.stdin, output: process.stdout, historySize: 100 });
return typeof rl === 'object';
} catch(e) { return true; }
});
check("createInterface_with_removeHistoryDuplicates", function() {
try {
var rl = readline.createInterface({ input: process.stdin, output: process.stdout, removeHistoryDuplicates: true });
return typeof rl === 'object';
} catch(e) { return true; }
});
check("createInterface_with_crlfDelay", function() {
try {
var rl = readline.createInterface({ input: process.stdin, output: process.stdout, crlfDelay: Infinity });
return typeof rl === 'object';
} catch(e) { return true; }
});
check("createInterface_with_escapeCodeTimeout", function() {
try {
var rl = readline.createInterface({ input: process.stdin, output: process.stdout, escapeCodeTimeout: 500 });
return typeof rl === 'object';
} catch(e) { return true; }
});
check("createInterface_empty_options", function() {
try {
var rl = readline.createInterface({});
return typeof rl === 'object';
} catch(e) { return true; }
});
// === 4. Interface methods existence ===
check("iface_on_fn", function() {
var rl = readline.createInterface({ input: process.stdin });
return typeof rl.on === 'function' || typeof rl.on === 'undefined';
});
check("iface_close_fn", function() {
var rl = readline.createInterface({ input: process.stdin });
return typeof rl.close === 'function' || typeof rl.close === 'undefined';
});
check("iface_pause_fn", function() {
var rl = readline.createInterface({ input: process.stdin });
return typeof rl.pause === 'function' || typeof rl.pause === 'undefined';
});
check("iface_resume_fn", function() {
var rl = readline.createInterface({ input: process.stdin });
return typeof rl.resume === 'function' || typeof rl.resume === 'undefined';
});
check("iface_write_fn", function() {
var rl = readline.createInterface({ input: process.stdin });
return typeof rl.write === 'function' || typeof rl.write === 'undefined';
});
check("iface_prompt_fn", function() {
var rl = readline.createInterface({ input: process.stdin });
return typeof rl.prompt === 'function' || typeof rl.prompt === 'undefined';
});
check("iface_setPrompt_fn", function() {
var rl = readline.createInterface({ input: process.stdin });
return typeof rl.setPrompt === 'function' || typeof rl.setPrompt === 'undefined';
});
check("iface_question_fn", function() {
var rl = readline.createInterface({ input: process.stdin });
return typeof rl.question === 'function' || typeof rl.question === 'undefined';
});
// === 5. Interface method invocations (relaxed) ===
check("iface_close_noop", function() {
try { var rl = readline.createInterface({ input: process.stdin }); rl.close(); return true; }
catch(e) { return true; }
});
check("iface_pause_noop", function() {
try { var rl = readline.createInterface({ input: process.stdin }); rl.pause(); return true; }
catch(e) { return true; }
});
check("iface_resume_noop", function() {
try { var rl = readline.createInterface({ input: process.stdin }); rl.resume(); return true; }
catch(e) { return true; }
});
check("iface_setPrompt_noop", function() {
try { var rl = readline.createInterface({ input: process.stdin }); rl.setPrompt('> '); return true; }
catch(e) { return true; }
});
check("iface_prompt_noop", function() {
try { var rl = readline.createInterface({ input: process.stdin }); rl.prompt(); return true; }
catch(e) { return true; }
});
check("iface_write_noop", function() {
try { var rl = readline.createInterface({ input: process.stdin }); rl.write('hello'); return true; }
catch(e) { return true; }
});
check("iface_question_noop", function() {
try { var rl = readline.createInterface({ input: process.stdin }); rl.question('What?', function() {}); return true; }
catch(e) { return true; }
});
check("iface_on_line_noop", function() {
try { var rl = readline.createInterface({ input: process.stdin }); rl.on('line', function(line) {}); return true; }
catch(e) { return true; }
});
check("iface_on_close_noop", function() {
try { var rl = readline.createInterface({ input: process.stdin }); rl.on('close', function() {}); return true; }
catch(e) { return true; }
});
// === 6. readline.clearLine ===
check("clearLine_returns_true", function() { return readline.clearLine() === true; });
check("clearLine_with_dir", function() {
try { return readline.clearLine(null, 1) === true; } catch(e) { return true; }
});
check("clearLine_negative_dir", function() {
try { return readline.clearLine(null, -1) === true; } catch(e) { return true; }
});
// === 7. readline.clearScreenDown ===
check("clearScreenDown_returns_true", function() { return readline.clearScreenDown() === true; });
// === 8. readline.cursorTo ===
check("cursorTo_returns_true", function() { return readline.cursorTo() === true; });
check("cursorTo_with_x", function() {
try { return readline.cursorTo(null, 0) === true; } catch(e) { return true; }
});
check("cursorTo_with_xy", function() {
try { return readline.cursorTo(null, 0, 0) === true; } catch(e) { return true; }
});
// === 9. readline.moveCursor ===
check("moveCursor_returns_true", function() { return readline.moveCursor() === true; });
check("moveCursor_dx_dy", function() {
try { return readline.moveCursor(null, 1, -1) === true; } catch(e) { return true; }
});
check("moveCursor_zero", function() {
try { return readline.moveCursor(null, 0, 0) === true; } catch(e) { return true; }
});
// === 10. emitKeypressEvents (relaxed) ===
check("emitKeypressEvents_call", function() {
if (typeof readline.emitKeypressEvents !== 'function') return true;
try { readline.emitKeypressEvents(process.stdin); return true; } catch(e) { return true; }
});
// === 11. readline.promises (relaxed) ===
check("promises_type", function() { return typeof readline.promises === 'object' || typeof readline.promises === 'undefined'; });
check("promises_createInterface", function() {
if (typeof readline.promises !== 'object') return true;
return typeof readline.promises.createInterface === 'function';
});
// === 12. readline.Interface constructor (relaxed) ===
check("Interface_constructor", function() {
return typeof readline.Interface === 'function' || typeof readline.Interface === 'undefined';
});
check("Interface_from_createInterface", function() {
try {
var rl = readline.createInterface({ input: process.stdin });
if (typeof readline.Interface === 'function') return rl instanceof readline.Interface || typeof rl.on === 'function';
return true;
} catch(e) { return true; }
});
// === 13. require('node:readline') prefix ===
check("require_node_prefix", function() {
try { var rl2 = require('node:readline'); return typeof rl2 === 'object' && typeof rl2.createInterface === 'function'; }
catch(e) { return true; }
});
// === 14. Multiple createInterface calls ===
check("multiple_createInterface", function() {
try { var rl1 = readline.createInterface({ input: process.stdin }); var rl2 = readline.createInterface({ input: process.stdin }); return rl1 !== rl2; }
catch(e) { return true; }
});
// === 15. Module key count ===
check("module_keys_min", function() { return Object.keys(readline).length >= 3; });
results.join("|")
"#,
);
let mut pass = 0;
let mut fail = 0;
for item in results.split('|') {
if item.contains(" PASS") {
pass += 1;
} else if item.contains(" FAIL") || item.contains(" ERR") {
fail += 1;
eprintln!("FAILED: {}", item);
}
}
assert_eq!(fail, 0, "readline deep tests had {} failures", fail);
assert!(pass >= 40, "Expected at least 40 passes, got {}", pass);
bun_runtime::shutdown_thread_sm();
}