use crate::wire::RunnerKind;
use std::path::PathBuf;
#[cfg(target_os = "windows")]
pub fn webview2_data_dir(kind: &RunnerKind, runner_id: &str) -> Option<PathBuf> {
let local_app_data = std::env::var("LOCALAPPDATA")
.ok()
.filter(|s| !s.is_empty())?;
let base = PathBuf::from(local_app_data).join("com.qontinui.runner");
match kind {
RunnerKind::Primary => Some(base.join("EBWebView")),
_ => Some(base.join(format!("EBWebView-{}", sanitize(runner_id)))),
}
}
#[cfg(not(target_os = "windows"))]
pub fn webview2_data_dir(_kind: &RunnerKind, _runner_id: &str) -> Option<PathBuf> {
None
}
#[cfg(target_os = "windows")]
fn sanitize(s: &str) -> String {
s.chars()
.map(|c| {
if c.is_ascii_alphanumeric() || c == '-' || c == '_' {
c
} else {
'_'
}
})
.collect()
}
#[cfg(all(test, target_os = "windows"))]
mod tests {
use super::*;
fn with_local_app_data<R>(f: impl FnOnce(PathBuf) -> R) -> Option<R> {
let lad = std::env::var("LOCALAPPDATA")
.ok()
.filter(|s| !s.is_empty())?;
Some(f(PathBuf::from(lad).join("com.qontinui.runner")))
}
#[test]
fn primary_uses_default_folder() {
let _ = with_local_app_data(|base| {
let dir = webview2_data_dir(&RunnerKind::Primary, "primary").unwrap();
assert_eq!(dir, base.join("EBWebView"));
let dir = webview2_data_dir(&RunnerKind::Primary, "test-foo").unwrap();
assert_eq!(dir, base.join("EBWebView"));
});
}
#[test]
fn temp_uses_id_suffix() {
let _ = with_local_app_data(|base| {
let kind = RunnerKind::Temp {
id: "test-abc123".into(),
};
let dir = webview2_data_dir(&kind, "test-abc123").unwrap();
assert_eq!(dir, base.join("EBWebView-test-abc123"));
});
}
#[test]
fn named_uses_id_suffix_not_name() {
let _ = with_local_app_data(|base| {
let kind = RunnerKind::Named {
name: "Friendly Name".into(),
};
let dir = webview2_data_dir(&kind, "named-9880-deadbeef").unwrap();
assert_eq!(dir, base.join("EBWebView-named-9880-deadbeef"));
assert!(!dir.to_string_lossy().contains("Friendly"));
});
}
#[test]
fn external_uses_id_suffix() {
let _ = with_local_app_data(|base| {
let dir = webview2_data_dir(&RunnerKind::External, "user-runner-1").unwrap();
assert_eq!(dir, base.join("EBWebView-user-runner-1"));
});
}
#[test]
fn sanitizes_unsafe_characters() {
let _ = with_local_app_data(|base| {
let kind = RunnerKind::Temp {
id: "test-a/b\\c d.e".into(),
};
let dir = webview2_data_dir(&kind, "test-a/b\\c d.e").unwrap();
assert_eq!(dir, base.join("EBWebView-test-a_b_c_d_e"));
});
}
#[test]
fn preserves_alphanumeric_dash_underscore() {
assert_eq!(sanitize("abc-123_DEF"), "abc-123_DEF");
}
}
#[cfg(all(test, not(target_os = "windows")))]
mod tests {
use super::*;
#[test]
fn returns_none_on_non_windows() {
assert!(webview2_data_dir(&RunnerKind::Primary, "primary").is_none());
assert!(webview2_data_dir(
&RunnerKind::Temp {
id: "test-x".into()
},
"test-x"
)
.is_none());
}
}