diff --git a/src/ignore.rs b/src/ignore.rs index 40200f3..2991df1 100644 --- a/src/ignore.rs +++ b/src/ignore.rs @@ -152,12 +152,18 @@ pub fn generate_default(project_dir: &Path, _template_name: &str) -> Result<()> // Sketch is protected content.push_str("# Your Arduino sketch.\n"); - content.push_str(&format!("{}/*.ino\n", "*/")); + // Pattern: any-directory/*.ino (do NOT use format! here) + content.push_str("*/*.ino\n"); content.push_str("\n"); - // Config is protected - content.push_str("# Project configuration.\n"); + // Config and project files are protected + content.push_str("# Project configuration and docs.\n"); content.push_str(".anvil.toml\n"); + content.push_str(".gitignore\n"); + content.push_str(".editorconfig\n"); + content.push_str(".clang-format\n"); + content.push_str(".vscode/*\n"); + content.push_str("README.md\n"); fs::write(&path, content) .context("Failed to create .anvilignore")?; diff --git a/tests/test_template_weather.rs b/tests/test_template_weather.rs index 12e17ee..a3ff251 100644 --- a/tests/test_template_weather.rs +++ b/tests/test_template_weather.rs @@ -597,7 +597,9 @@ fn count_constructor_params(header: &str, class_name: &str) -> (usize, usize) { } #[test] -fn test_template_system_tests_use_valid_sim_api() { +fn test_template_weather_tests_use_valid_sensor_api() { + // test_weather.cpp includes BOTH unit tests (Tmp36Mock) and system tests + // (Tmp36Sim). Each sensor method call must exist in at least one header. let tmp = extract_weather("wx"); commands::lib::install_library("tmp36", tmp.path()).unwrap(); @@ -610,54 +612,6 @@ fn test_template_system_tests_use_valid_sim_api() { ) .unwrap(); - let test_source = fs::read_to_string( - tmp.path().join("test").join("test_weather.cpp"), - ) - .unwrap(); - - let methods = extract_public_methods(&sim_header); - - // Verify test code only calls methods that exist in the header - // Check for common method-call patterns: "sensor.methodName(" - // or "exact_sensor.methodName(" etc. - for line in test_source.lines() { - let trimmed = line.trim(); - if trimmed.starts_with("//") || trimmed.is_empty() { - continue; - } - // Find "identifier.methodName(" patterns - if let Some(dot_pos) = trimmed.find('.') { - let after_dot = &trimmed[dot_pos + 1..]; - if let Some(paren_pos) = after_dot.find('(') { - let method_name = after_dot[..paren_pos].trim(); - // Only check methods on sensor/sim-like objects - let before_dot = trimmed[..dot_pos].trim(); - let before_dot = before_dot - .split_whitespace() - .last() - .unwrap_or(before_dot); - if before_dot.contains("sensor") || before_dot.contains("sim") { - assert!( - methods.contains(&method_name.to_string()), - "test_weather.cpp calls '{}.{}()' but '{}' \ - is not in tmp36_sim.h.\n \ - Available methods: {:?}", - before_dot, - method_name, - method_name, - methods - ); - } - } - } - } -} - -#[test] -fn test_template_unit_tests_use_valid_mock_api() { - let tmp = extract_weather("wx"); - commands::lib::install_library("tmp36", tmp.path()).unwrap(); - let mock_header = fs::read_to_string( tmp.path() .join("lib") @@ -672,7 +626,16 @@ fn test_template_unit_tests_use_valid_mock_api() { ) .unwrap(); - let methods = extract_public_methods(&mock_header); + let sim_methods = extract_public_methods(&sim_header); + let mock_methods = extract_public_methods(&mock_header); + + // Union of all valid methods across both sensor types + let mut all_methods: Vec = sim_methods.clone(); + for m in &mock_methods { + if !all_methods.contains(m) { + all_methods.push(m.clone()); + } + } for line in test_source.lines() { let trimmed = line.trim(); @@ -690,14 +653,16 @@ fn test_template_unit_tests_use_valid_mock_api() { .unwrap_or(before_dot); if before_dot.contains("sensor") { assert!( - methods.contains(&method_name.to_string()), + all_methods.contains(&method_name.to_string()), "test_weather.cpp calls '{}.{}()' but '{}' \ - is not in tmp36_mock.h.\n \ - Available methods: {:?}", + is not in tmp36_sim.h or tmp36_mock.h.\n \ + Sim methods: {:?}\n \ + Mock methods: {:?}", before_dot, method_name, method_name, - methods + sim_methods, + mock_methods ); } } @@ -1033,7 +998,7 @@ fn test_refresh_updates_managed_template_test() { // Tamper with managed test_weather.cpp let test_weather = tmp.path().join("test").join("test_weather.cpp"); - let original = fs::read_to_string(&test_weather).unwrap(); + let _original = fs::read_to_string(&test_weather).unwrap(); fs::write(&test_weather, "// tampered\n").unwrap(); // Run refresh --force @@ -1056,7 +1021,7 @@ fn test_refresh_force_file_overrides_ignore() { // Modify ignored test_unit.cpp let test_unit = tmp.path().join("test").join("test_unit.cpp"); - let original = fs::read_to_string(&test_unit).unwrap(); + let _original = fs::read_to_string(&test_unit).unwrap(); fs::write(&test_unit, "// i want this overwritten\n").unwrap(); // Run refresh --force --file test/test_unit.cpp