use crate::*;
#[test]
fn chrome_preset_exposes_expected_identity() {
let persona = BrowserPersona::from_preset(BrowserPersonaPreset::ChromeStable);
assert_eq!(persona.browser_name, "Chrome");
assert!(persona.network.user_agent.contains("Chrome/136"));
assert_eq!(persona.graphics.webgl_vendor, "Intel Inc.");
assert_eq!(persona.graphics.webgl_masked_vendor, "WebKit");
assert_eq!(persona.graphics.webgl_masked_renderer, "WebKit WebGL");
assert!(!persona.automation.webdriver);
}
#[test]
fn stable_seed_is_deterministic() {
assert_eq!(
PersonaSeed::from_stable_input("/tmp/profile").as_str(),
PersonaSeed::from_stable_input("/tmp/profile").as_str()
);
assert_ne!(
PersonaSeed::from_stable_input("/tmp/profile-a").as_str(),
PersonaSeed::from_stable_input("/tmp/profile-b").as_str()
);
}
#[test]
fn persona_config_resolves_seed_and_viewport() {
let persona = PersonaConfig {
startup_url: Some(" https://example.com/start ".to_string()),
seed: Some(PersonaSeed::new("session-a")),
viewport: Viewport {
width: 1280,
height: 720,
device_scale_factor: 2,
},
..Default::default()
}
.resolve();
assert_eq!(persona.seed.as_str(), "session-a");
assert_eq!(
persona.startup_url.as_deref(),
Some("https://example.com/start")
);
assert_eq!(persona.viewport.width, 1280);
assert_eq!(persona.screen.avail_height, 720);
assert_eq!(persona.screen.device_scale_factor, 2);
}
#[test]
fn persona_config_applies_screen_depth_overrides() {
let persona = PersonaConfig {
viewport: Viewport {
width: 1728,
height: 1117,
device_scale_factor: 2,
},
screen: Some(ScreenConfig {
avail_height: Some(1079),
avail_left: Some(0),
avail_top: Some(25),
left: Some(0),
top: Some(0),
color_depth: Some(30),
pixel_depth: Some(30),
is_extended: Some(false),
orientation_type: Some("landscape-primary".to_string()),
orientation_angle: Some(0),
..Default::default()
}),
..Default::default()
}
.resolve();
assert_eq!(persona.viewport.width, 1728);
assert_eq!(persona.viewport.device_scale_factor, 2);
assert_eq!(persona.screen.width, 1728);
assert_eq!(persona.screen.height, 1117);
assert_eq!(persona.screen.avail_height, 1079);
assert_eq!(persona.screen.avail_left, 0);
assert_eq!(persona.screen.avail_top, 25);
assert_eq!(persona.screen.left, 0);
assert_eq!(persona.screen.top, 0);
assert_eq!(persona.screen.color_depth, 30);
assert_eq!(persona.screen.pixel_depth, 30);
assert!(!persona.screen.is_extended);
assert_eq!(persona.screen.orientation_type, "landscape-primary");
assert_eq!(persona.screen.orientation_angle, 0);
}
#[test]
fn persona_config_applies_window_overrides() {
let persona = PersonaConfig {
viewport: Viewport {
width: 1710,
height: 896,
device_scale_factor: 2,
},
window: Some(WindowConfig {
outer_width: Some(1710),
outer_height: Some(1017),
screen_x: Some(0),
screen_y: Some(23),
}),
..Default::default()
}
.resolve();
assert_eq!(persona.viewport.width, 1710);
assert_eq!(persona.viewport.height, 896);
assert_eq!(persona.window.outer_width, 1710);
assert_eq!(persona.window.outer_height, 1017);
assert_eq!(persona.window.screen_x, 0);
assert_eq!(persona.window.screen_y, 23);
}
#[test]
fn persona_config_applies_css_prefix_overrides() {
let persona = PersonaConfig {
css: Some(CssConfig {
moz_prefix_enabled: Some(true),
webkit_prefix_enabled: Some(false),
}),
..Default::default()
}
.resolve();
assert!(persona.css.moz_prefix_enabled);
assert!(!persona.css.webkit_prefix_enabled);
}
#[test]
fn persona_config_applies_graphics_overrides() {
let persona = PersonaConfig {
graphics: Some(GraphicsConfig {
webgl_vendor: Some("Google Inc. (Intel Inc.)".to_string()),
webgl_renderer: Some(
"ANGLE (Intel Inc., Intel(R) UHD Graphics 630, OpenGL 4.1)".to_string(),
),
webgl_masked_vendor: Some("WebKit".to_string()),
webgl_masked_renderer: Some("WebKit WebGL".to_string()),
}),
..Default::default()
}
.resolve();
assert_eq!(persona.graphics.webgl_vendor, "Google Inc. (Intel Inc.)");
assert_eq!(
persona.graphics.webgl_renderer,
"ANGLE (Intel Inc., Intel(R) UHD Graphics 630, OpenGL 4.1)"
);
assert_eq!(persona.graphics.webgl_masked_vendor, "WebKit");
assert_eq!(persona.graphics.webgl_masked_renderer, "WebKit WebGL");
}
#[test]
fn persona_config_applies_navigator_overrides() {
let persona = PersonaConfig {
navigator: Some(NavigatorConfig {
platform: Some("Win32".to_string()),
languages: Some(vec!["en-GB".to_string(), "en".to_string()]),
hardware_concurrency: Some(12),
device_memory_gb: Some(16),
max_touch_points: Some(1),
do_not_track: Some("1".to_string()),
expose_global_privacy_control: Some(true),
global_privacy_control: Some(true),
permissions_enabled: Some(false),
bluetooth_enabled: Some(false),
bluetooth_available: Some(false),
media_devices_enabled: Some(false),
webgpu_enabled: Some(true),
offscreen_canvas_enabled: Some(false),
service_worker_enabled: Some(false),
ua_platform_version: Some("10.0.0".to_string()),
ua_architecture: Some("arm".to_string()),
ua_bitness: Some("64".to_string()),
ua_model: Some("Mac15,3".to_string()),
pdf_viewer_enabled: Some(false),
..Default::default()
}),
..Default::default()
}
.resolve();
assert_eq!(persona.js.platform, "Win32");
assert_eq!(persona.js.language, "en-GB");
assert_eq!(persona.js.languages, ["en-GB", "en"]);
assert_eq!(persona.network.accept_language, "en-GB,en;q=0.9");
assert_eq!(persona.js.hardware_concurrency, 12);
assert_eq!(persona.js.device_memory_gb, 16);
assert_eq!(persona.js.max_touch_points, 1);
assert_eq!(persona.js.do_not_track, "1");
assert!(persona.js.expose_global_privacy_control);
assert!(persona.js.global_privacy_control);
assert!(!persona.js.permissions_enabled);
assert!(!persona.js.bluetooth_enabled);
assert!(!persona.js.bluetooth_available);
assert!(!persona.js.media_devices_enabled);
assert!(persona.js.webgpu_enabled);
assert!(!persona.js.offscreen_canvas_enabled);
assert!(!persona.js.service_worker_enabled);
assert_eq!(persona.js.ua_platform_version, "10.0.0");
assert_eq!(persona.js.ua_architecture, "arm");
assert_eq!(persona.js.ua_bitness, "64");
assert_eq!(persona.js.ua_model, "Mac15,3");
assert!(!persona.js.pdf_viewer_enabled);
}
#[test]
fn persona_config_applies_media_device_overrides() {
let persona = PersonaConfig {
media: Some(MediaConfig {
speech_voices: Some(vec!["Samantha".to_string(), "Alex".to_string()]),
audio_inputs: Some(2),
video_inputs: Some(1),
audio_outputs: Some(3),
}),
..Default::default()
}
.resolve();
assert_eq!(persona.media.audio_inputs, 2);
assert_eq!(persona.media.video_inputs, 1);
assert_eq!(persona.media.audio_outputs, 3);
assert_eq!(persona.media.speech_voices, ["Samantha", "Alex"]);
}
#[test]
fn persona_config_applies_font_overrides() {
let persona = PersonaConfig {
fonts: Some(FontConfig {
families: Some(vec![
"Helvetica Neue".to_string(),
" ".to_string(),
"Galvji".to_string(),
]),
seed: Some(PersonaSeed::new("font-test-seed")),
}),
..Default::default()
}
.resolve();
assert_eq!(persona.fonts.families, ["Helvetica Neue", "Galvji"]);
assert_eq!(persona.fonts.seed.as_str(), "font-test-seed");
}
#[test]
fn persona_config_applies_canvas_overrides() {
let persona = PersonaConfig {
canvas: Some(CanvasConfig {
noise_enabled: Some(false),
noise_amplitude: Some(2),
blink_low_entropy_probe: Some(false),
seed: Some(PersonaSeed::new("canvas-test-seed")),
}),
..Default::default()
}
.resolve();
assert!(!persona.canvas.noise_enabled);
assert_eq!(persona.canvas.noise_amplitude, 2);
assert!(!persona.canvas.blink_low_entropy_probe);
assert_eq!(persona.canvas.seed.as_str(), "canvas-test-seed");
}
#[test]
fn persona_config_applies_domrect_overrides() {
let persona = PersonaConfig {
domrect: Some(DomRectConfig {
enabled: Some(false),
quantization_steps_per_px: Some(128),
fill_empty_client_rects: Some(false),
seed: Some(PersonaSeed::new("domrect-test-seed")),
}),
..Default::default()
}
.resolve();
assert!(!persona.domrect.enabled);
assert_eq!(persona.domrect.quantization_steps_per_px, 128);
assert!(!persona.domrect.fill_empty_client_rects);
assert_eq!(persona.domrect.seed.as_str(), "domrect-test-seed");
}
#[test]
fn persona_config_applies_engine_overrides() {
let persona = PersonaConfig {
engine: Some(EngineConfig {
enabled: Some(false),
to_fixed_range_error_message: Some("digits are invalid".to_string()),
array_constructor_source: Some("function Array() { [native code] }".to_string()),
}),
..Default::default()
}
.resolve();
assert!(!persona.engine.enabled);
assert_eq!(
persona.engine.to_fixed_range_error_message,
"digits are invalid"
);
assert_eq!(
persona.engine.array_constructor_source,
"function Array() { [native code] }"
);
}
#[test]
fn resolved_persona_round_trips_through_json() {
let persona = PersonaConfig {
seed: Some(PersonaSeed::new("round-trip")),
..Default::default()
}
.resolve();
let encoded = serde_json::to_string(&persona).unwrap();
let decoded: ResolvedPersona = serde_json::from_str(&encoded).unwrap();
assert_eq!(decoded, persona);
}
#[test]
fn persona_config_applies_locale_timezone_and_accept_language_together() {
let persona: ResolvedPersona = serde_json::from_str::<PersonaConfig>(
r#"{
"locale": "fr-FR",
"languages": ["fr-FR", "fr"],
"accept_language": "fr-FR,fr;q=0.9",
"timezone": "Europe/Paris"
}"#,
)
.unwrap()
.resolve();
assert_eq!(persona.js.language, "fr-FR");
assert_eq!(persona.js.languages, ["fr-FR", "fr"]);
assert_eq!(persona.geo.locale, "fr-FR");
assert_eq!(persona.network.accept_language, "fr-FR,fr;q=0.9");
assert_eq!(persona.js.timezone, "Europe/Paris");
assert_eq!(persona.geo.timezone, "Europe/Paris");
}
#[test]
fn persona_config_derives_languages_from_accept_language() {
let persona = PersonaConfig {
accept_language: Some("de-DE,de;q=0.9".to_string()),
..Default::default()
}
.resolve();
assert_eq!(persona.js.language, "de-DE");
assert_eq!(persona.js.languages, ["de-DE", "de"]);
assert_eq!(persona.geo.locale, "de-DE");
assert_eq!(persona.network.accept_language, "de-DE,de;q=0.9");
}