mod common;
use common::{Detector, dump};
use std::time::Duration;
const URL: &str = "https://www.browserscan.net/";
const READY: &str = r#"(() => {
const t = document.body ? document.body.innerText : '';
return /Robot|Incognito|IP address/i.test(t) ? 'yes' : 'no';
})()"#;
const QUOTA: &str = r#"(async () => {
const out = {};
try { out.jsHeapSizeLimit = performance.memory.jsHeapSizeLimit; } catch (e) {}
const quota = await new Promise((r) => {
try {
if (navigator.webkitTemporaryStorage && navigator.webkitTemporaryStorage.queryUsageAndQuota) {
navigator.webkitTemporaryStorage.queryUsageAndQuota((u, q) => r(q), () => r(null));
} else if (navigator.storage && navigator.storage.estimate) {
navigator.storage.estimate().then((e) => r(e.quota)).catch(() => r(null));
} else r(null);
} catch (e) { r(null); }
});
out.quota = quota;
if (quota && out.jsHeapSizeLimit) {
out.quotaMiB = Math.round(quota / 1048576);
out.barMiB = Math.round(out.jsHeapSizeLimit / 1048576) * 2;
out.isPrivate = out.quotaMiB < out.barMiB;
}
return JSON.stringify(out);
})()"#;
const SCRAPE: &str = r#"(() => {
const text = document.body ? document.body.innerText : '';
const after = (label) => {
const re = new RegExp(label + '\\s*\\n\\s*([^\\n]{1,60})', 'i');
const m = text.match(re);
return m ? m[1].trim() : null;
};
return JSON.stringify({
incognito: after('Incognito'),
robot: after('Robot'),
webdriver: after('WebDriver'),
userAgent: after('User Agent'),
platform: after('Platform'),
net: (window.__net || []).map((n) => ({ url: n.url, status: n.status })),
});
})()"#;
#[tokio::test]
#[ignore = "launches a browser and hits the network"]
async fn incognito_is_not_reported() {
let mut d = Detector::open(1, URL).await;
d.wait_until(READY, Duration::from_secs(90)).await;
let quota = d.eval_async(QUOTA).await;
dump("detectIncognito arithmetic", "a);
assert!(
quota["quota"].is_number(),
"could not read the storage quota — the probe returned {quota}"
);
let report = d.eval(SCRAPE).await;
dump("browserscan", &report);
d.close().await;
let is_private = quota["isPrivate"].as_bool();
assert_ne!(
is_private,
Some(true),
"browserscan reports incognito: quota {} MiB is under the {} MiB bar. \
Chrome's profile is on a filesystem too small — check where user_data_dir \
points (std::env::temp_dir() is /tmp, a tmpfs on Debian 13).",
quota["quotaMiB"],
quota["barMiB"],
);
if let Some(row) = report["incognito"].as_str() {
assert!(
!row.eq_ignore_ascii_case("yes"),
"browserscan's incognito row says {row:?}"
);
}
}
#[tokio::test]
#[ignore = "launches a browser and hits the network"]
async fn robot_detection_passes() {
let mut d = Detector::open(1, URL).await;
d.wait_until(READY, Duration::from_secs(90)).await;
let report = d.eval(SCRAPE).await;
dump("browserscan", &report);
let traffic = d.traffic().await;
dump("traffic", &traffic);
d.close().await;
if let Some(robot) = report["robot"].as_str() {
assert!(
!robot.to_lowercase().contains("yes") && !robot.to_lowercase().contains("detected"),
"browserscan's robot row says {robot:?}"
);
}
}