//! Integration tests for CAD workspace and file store. //! //! These tests cover file-backed CAD operations and active project state. //! Full widget UI tests would require the makepad test harness (window + event loop). use std::fs; use std::path::PathBuf; /// Helper: creates a unique temporary directory and returns its path. fn temp_dir() -> PathBuf { let dir = std::env::temp_dir().join(format!( "nigig_cad_test_{}_{}", std::process::id(), rand_id() )); fs::create_dir_all(&dir).unwrap(); dir } fn rand_id() -> u64 { use std::time::{SystemTime, UNIX_EPOCH}; SystemTime::now() .duration_since(UNIX_EPOCH) .map(|d| d.as_nanos() as u64) .unwrap_or(0) } fn cleanup(dir: &PathBuf) { let _ = fs::remove_dir_all(dir); } // ── cad_store file tests ───────────────────────────────────────── #[test] fn save_and_load_cad_script_by_path() { let dir = temp_dir(); let path = dir.join("test_project.cad"); let script = "render(cube(1.0, 1.0, 1.0, true))"; nigig_build::cad_store::save_cad_script_to_path(&path, script).unwrap(); assert!(path.exists()); let loaded = nigig_build::cad_store::load_cad_script_from_path(&path).unwrap(); assert_eq!(loaded, script); cleanup(&dir); } #[test] fn load_nonexistent_script_returns_error() { let dir = temp_dir(); let path = dir.join("nonexistent.cad"); let result = nigig_build::cad_store::load_cad_script_from_path(&path); assert!(result.is_err()); cleanup(&dir); } #[test] fn save_cad_script_creates_parent_dirs() { let dir = temp_dir(); let path = dir.join("subdir").join("nested").join("model.cad"); nigig_build::cad_store::save_cad_script_to_path(&path, "render(sphere(0.5, 16, 8))").unwrap(); assert!(path.exists()); cleanup(&dir); } #[test] fn save_and_load_empty_script() { let dir = temp_dir(); let path = dir.join("empty.cad"); nigig_build::cad_store::save_cad_script_to_path(&path, "").unwrap(); let loaded = nigig_build::cad_store::load_cad_script_from_path(&path).unwrap(); assert_eq!(loaded, ""); cleanup(&dir); } #[test] fn save_and_load_unicode_script() { let dir = temp_dir(); let path = dir.join("unicode.cad"); let script = "// Note: 尺寸测试\nrender(cube(1.0, 2.0, 3.0, true))"; nigig_build::cad_store::save_cad_script_to_path(&path, script).unwrap(); let loaded = nigig_build::cad_store::load_cad_script_from_path(&path).unwrap(); assert_eq!(loaded, script); cleanup(&dir); } #[test] fn overwrite_existing_script() { let dir = temp_dir(); let path = dir.join("overwrite.cad"); nigig_build::cad_store::save_cad_script_to_path(&path, "version 1").unwrap(); nigig_build::cad_store::save_cad_script_to_path(&path, "version 2").unwrap(); let loaded = nigig_build::cad_store::load_cad_script_from_path(&path).unwrap(); assert_eq!(loaded, "version 2"); cleanup(&dir); } // ── ActiveProject state tests ──────────────────────────────────── #[test] fn active_project_defaults_to_none() { let p = nigig_build::cad_store::get_active_project(); assert!(p.is_none()); } #[test] fn set_and_get_active_project() { nigig_build::cad_store::set_active_project(nigig_build::cad_store::ActiveProject { id: "proj_42".into(), name: "Test Project".into(), }); let p = nigig_build::cad_store::get_active_project().unwrap(); assert_eq!(p.id, "proj_42"); assert_eq!(p.name, "Test Project"); nigig_build::cad_store::clear_active_project(); assert!(nigig_build::cad_store::get_active_project().is_none()); } #[test] fn set_active_project_overwrites_previous() { nigig_build::cad_store::set_active_project(nigig_build::cad_store::ActiveProject { id: "first".into(), name: "First".into(), }); nigig_build::cad_store::set_active_project(nigig_build::cad_store::ActiveProject { id: "second".into(), name: "Second".into(), }); let p = nigig_build::cad_store::get_active_project().unwrap(); assert_eq!(p.id, "second"); assert_eq!(p.name, "Second"); nigig_build::cad_store::clear_active_project(); } // ── project_store + cad_store integration tests ────────────────── #[test] fn active_project_id_matches_cad_file_path() { let id = format!("proj_{}", rand_id()); nigig_build::cad_store::set_active_project(nigig_build::cad_store::ActiveProject { id: id.clone(), name: "Integration".into(), }); let p = nigig_build::cad_store::get_active_project().unwrap(); let file_path = nigig_build::cad_store::cad_file_path(&p.id); let expected_name = format!("{}.cad", id); assert!( file_path.to_string_lossy().ends_with(&expected_name), "file path {} should end with {}", file_path.display(), expected_name ); nigig_build::cad_store::clear_active_project(); } // ── Placeholder for future widget-level UI tests ───────────────── // To write UI integration tests for CadWorkspace, BuildProjectsPage, etc., // you need the makepad test framework which provides: // - LiveSet / LiveDependency loading // - AppMain with test harness // - Widget construction via register_widget // - Event simulation (finger_down, finger_up, etc.) // // Example structure (see makepad examples/test.rs): // // #[test] // fn cad_workspace_opens_with_default_script() { // let mut app = TestApp::new(); // app.load_live_set(include_str!("...")); // app.init(); // let ws = app.widget(ids!(CadWorkspace)); // let editor = ws.widget(ids!(cad_editor)); // assert!(editor.text().contains("cube")); // }