use std::fs; use std::fs::File; use std::io::Write; use std::path::Path; fn main() { println!("cargo:rerun-if-changed=tests/fixtures"); println!("cargo:rerun-if-changed=Cargo.toml"); // File 1: src/tests.rs for #[pg_test] let pg_dest_path = Path::new("src/tests.rs"); let mut pg_file = File::create(&pg_dest_path).unwrap(); // File 2: tests/tests.rs for standard #[test] integration let std_dest_path = Path::new("tests/tests.rs"); let mut std_file = File::create(&std_dest_path).unwrap(); // Write headers writeln!(std_file, "use jspg::util;").unwrap(); // Helper for snake_case conversion // let _to_snake_case = |s: &str| -> String { // s.chars().fold(String::new(), |mut acc, c| { // if c.is_uppercase() { // if !acc.is_empty() { // acc.push('_'); // } // acc.push(c.to_ascii_lowercase()); // } else if c == '-' || c == ' ' || c == '.' || c == '/' || c == ':' { // acc.push('_'); // } else if c.is_alphanumeric() { // acc.push(c); // } // acc // }) // }; // Walk tests/fixtures directly let fixtures_path = "tests/fixtures"; if Path::new(fixtures_path).exists() { for entry in fs::read_dir(fixtures_path).unwrap() { let entry = entry.unwrap(); let path = entry.path(); if path.extension().unwrap_or_default() == "json" { let file_name = path.file_stem().unwrap().to_str().unwrap(); // Parse the JSON file to find blocks let file = File::open(&path).unwrap(); let val: serde_json::Value = serde_json::from_reader(file).unwrap(); if let Some(arr) = val.as_array() { for (i, _item) in arr.iter().enumerate() { // Use deterministic names: test_{filename}_{index} // We sanitize the filename to be a valid identifier // Use manual snake_case logic since we don't want to add a build-dependency just yet if not needed, // but `dynamicRef` -> `dynamic_ref` requires parsing. // Let's implement a simple camelToSnake helper. let mut safe_filename = String::new(); for (i, c) in file_name.chars().enumerate() { if c.is_uppercase() { if i > 0 { safe_filename.push('_'); } safe_filename.push(c.to_ascii_lowercase()); } else if c == '-' || c == '.' { safe_filename.push('_'); } else { safe_filename.push(c); } } let fn_name = format!("test_{}_{}", safe_filename, i); // Write to src/tests.rs (PG Test) // CARGO_MANIFEST_DIR is used to find the absolute path to fixtures at runtime write!( pg_file, r#" #[pg_test] fn {}() {{ let path = format!("{{}}/tests/fixtures/{}.json", env!("CARGO_MANIFEST_DIR")); crate::util::run_test_file_at_index(&path, {}).unwrap(); }} "#, fn_name, file_name, i ) .unwrap(); // Write to tests/tests.rs (Std Test) write!( std_file, r#" #[test] fn {}() {{ let path = format!("{{}}/tests/fixtures/{}.json", env!("CARGO_MANIFEST_DIR")); util::run_test_file_at_index(&path, {}).unwrap(); }} "#, fn_name, file_name, i ) .unwrap(); } } } } } }