nigig-org/crates/apps/nigig-build/tests/cad_ui.rs
2026-07-26 19:38:26 +03:00

195 lines
5.8 KiB
Rust

//! 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"));
// }