use std::fs;
use std::path::PathBuf;
use std::process::{Command, Output};
use std::sync::atomic::{AtomicU64, Ordering};
static NEXT_FIXTURE: AtomicU64 = AtomicU64::new(0);
struct Fixture {
root: PathBuf,
}
impl Fixture {
fn new() -> Self {
let root = std::env::temp_dir().join(format!(
"noxid-wo29-devtools-privacy-{}-{}",
std::process::id(),
NEXT_FIXTURE.fetch_add(1, Ordering::Relaxed)
));
fs::create_dir_all(root.join("src/routes")).expect("create DevTools fixture");
fs::write(
root.join("Noxid.toml"),
"[app]\ntitle = \"Metadata privacy\"\nbase = \"/shop\"\n",
)
.expect("write manifest");
fs::write(
root.join("src/routes/+page.nox"),
"component Home { state { count: Int = 0 } route { title: \"Home\" } view { <main>{count}</main> } }\n",
)
.expect("write route");
Self { root }
}
fn build(&self, out_dir: &str) -> Output {
let mut command = Command::new(env!("CARGO_BIN_EXE_noxid"));
command.args(["build", ".", "--out-dir", out_dir]);
command
.current_dir(&self.root)
.output()
.expect("build DevTools privacy fixture")
}
}
impl Drop for Fixture {
fn drop(&mut self) {
let _ = fs::remove_dir_all(&self.root);
}
}
fn assert_success(output: &Output, context: &str) {
assert!(
output.status.success(),
"{context}\nstdout:\n{}\nstderr:\n{}",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
}
#[test]
fn production_devtools_metadata_contains_only_project_relative_source_paths() {
let fixture = Fixture::new();
let production = fixture.build("dist");
assert_success(&production, "build production metadata fixture");
let metadata = fs::read_to_string(fixture.root.join("dist/app.devtools.json"))
.expect("read production DevTools metadata");
let absolute_root = fixture.root.to_string_lossy();
assert!(
!metadata.contains(absolute_root.as_ref()),
"production metadata leaked project root {absolute_root}: {metadata}"
);
assert!(metadata.contains("\"source\": \".\""), "{metadata}");
assert!(
metadata.contains("\"source\":\"src/routes/+page.nox\""),
"{metadata}"
);
}