use bao_engine::context::JsContext;
use bao_engine::value::JsValue;
fn eval_bool(ctx: &mut JsContext, source: &str) -> bool {
match ctx.eval(source, "<test>") {
Ok(JsValue::Bool(b)) => b,
_ => false,
}
}
#[test]
fn test_stealth_http_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);
assert!(
eval_bool(&mut ctx, "typeof Bao === 'object'"),
"Bao should be object"
);
assert!(
eval_bool(&mut ctx, "Bao === Bun"),
"Bao should be Bun alias"
);
let chrome_profile = bao_stealth::StealthProfile::chrome_default();
let chrome_ja3 = bun_runtime::stealth_http::ja3_hash(&Some(chrome_profile.clone()));
assert!(
chrome_ja3.is_some(),
"ja3_hash with Chrome profile should return Some"
);
assert!(
chrome_ja3.as_ref().unwrap().starts_with("771,"),
"Chrome JA3 should start with 771, got: {}",
chrome_ja3.as_ref().unwrap_or(&String::new())
);
let ff_profile = bao_stealth::StealthProfile::firefox_default();
let ff_ja3 = bun_runtime::stealth_http::ja3_hash(&Some(ff_profile.clone()));
assert!(
ff_ja3.is_some(),
"ja3_hash with Firefox profile should return Some"
);
assert!(
ff_ja3.as_ref().unwrap().starts_with("771,"),
"Firefox JA3 should start with 771, got: {}",
ff_ja3.as_ref().unwrap_or(&String::new())
);
assert_ne!(
chrome_ja3, ff_ja3,
"Chrome and Firefox JA3 hashes must differ"
);
let none_ja3 = bun_runtime::stealth_http::ja3_hash(&None);
assert!(none_ja3.is_none(), "ja3_hash with None should return None");
let chrome_akamai =
bun_runtime::stealth_http::akamai_fingerprint(&Some(chrome_profile.clone()));
assert!(
chrome_akamai.is_some(),
"akamai_fingerprint with Chrome should return Some"
);
let ak_parts: Vec<&str> = chrome_akamai.as_ref().unwrap().split(':').collect();
assert_eq!(
ak_parts.len(),
6,
"Akamai fingerprint should have 6 colon-separated fields"
);
let ff_akamai = bun_runtime::stealth_http::akamai_fingerprint(&Some(ff_profile.clone()));
assert!(
ff_akamai.is_some(),
"akamai_fingerprint with Firefox should return Some"
);
assert_ne!(
chrome_akamai, ff_akamai,
"Chrome and Firefox Akamai fingerprints must differ"
);
let none_akamai = bun_runtime::stealth_http::akamai_fingerprint(&None);
assert!(
none_akamai.is_none(),
"akamai_fingerprint with None should return None"
);
let headers = vec![
("accept".to_string(), "*/*".to_string()),
("host".to_string(), "example.com".to_string()),
("content-type".to_string(), "text/html".to_string()),
];
let ordered_none = bun_runtime::stealth_http::ordered_headers(&None, &headers);
assert_eq!(
ordered_none.len(),
3,
"ordered_headers without profile should preserve count"
);
assert_eq!(ordered_none[0].0, "accept");
assert_eq!(ordered_none[1].0, "host");
assert_eq!(ordered_none[2].0, "content-type");
let pseudo_headers = vec![
("content-length".to_string(), "100".to_string()),
(":method".to_string(), "GET".to_string()),
(":authority".to_string(), "example.com".to_string()),
(":scheme".to_string(), "https".to_string()),
(":path".to_string(), "/".to_string()),
("accept".to_string(), "*/*".to_string()),
];
let ordered_chrome =
bun_runtime::stealth_http::ordered_headers(&Some(chrome_profile.clone()), &pseudo_headers);
assert!(
ordered_chrome[0].0.starts_with(':'),
"Chrome: first header should be pseudo-header, got: {}",
ordered_chrome[0].0
);
assert!(
ordered_chrome[1].0.starts_with(':'),
"Chrome: second header should be pseudo-header, got: {}",
ordered_chrome[1].0
);
let ordered_ff =
bun_runtime::stealth_http::ordered_headers(&Some(ff_profile.clone()), &pseudo_headers);
assert!(
ordered_ff[0].0.starts_with(':'),
"Firefox: first header should be pseudo-header, got: {}",
ordered_ff[0].0
);
let empty: Vec<(String, String)> = Vec::new();
let ordered_empty = bun_runtime::stealth_http::ordered_headers(&None, &empty);
assert!(
ordered_empty.is_empty(),
"ordered_headers with empty input should return empty"
);
let single = vec![("host".to_string(), "example.com".to_string())];
let ordered_single = bun_runtime::stealth_http::ordered_headers(&None, &single);
assert_eq!(ordered_single.len(), 1);
assert_eq!(ordered_single[0].0, "host");
let chrome_ja3_val = bun_runtime::stealth_http::ja3_hash(&Some(chrome_profile.clone()));
let ff_ja3_val = bun_runtime::stealth_http::ja3_hash(&Some(ff_profile.clone()));
assert_ne!(
chrome_ja3_val, ff_ja3_val,
"Chrome and Firefox must produce different JA3"
);
bun_runtime::shutdown_thread_sm();
}