use super::super::*;
use indicatrix_cut_core::{ConstraintTier, Edit, TierTarget};
#[test]
fn status_text_reports_closed_for_a_fresh_design() {
let (text, is_problem) = status_text_and_is_problem(&EditorState::fresh().design);
assert!(text.starts_with("Closed"));
assert!(!is_problem);
}
#[test]
fn proportions_texts_dashes_out_a_design_with_no_tiers() {
let design = EditorState::fresh().design;
assert_eq!(
proportions_texts(&design),
(
"-".to_string(),
"-".to_string(),
"-".to_string(),
"-".to_string(),
"-".to_string(),
),
"a tierless design must never show the bare preform block's own \
numbers as if they were the stone's -- including total depth, which \
(unlike the other four fields) has no `Option`-driven '-' fallback \
of its own and relied entirely on this guard"
);
}
#[test]
fn status_text_reports_degenerate_once_pinched_flat() {
let mut state = EditorState::fresh();
state
.apply(Edit::AddTier {
index: 0,
tier: ConstraintTier {
angle_deg: 0.0,
name: "T".to_string(),
indices: vec![],
constraint: indicatrix::geometry::meet_solver::MeetConstraint::ScaleReference(0.0),
imported_meet: None,
original_notes: None,
detached: Vec::new(),
},
})
.unwrap();
state
.apply(Edit::AddTier {
index: 1,
tier: ConstraintTier {
angle_deg: -0.0,
name: "C".to_string(),
indices: vec![],
constraint: indicatrix::geometry::meet_solver::MeetConstraint::ScaleReference(0.0),
imported_meet: None,
original_notes: None,
detached: Vec::new(),
},
})
.unwrap();
let (text, is_problem) = status_text_and_is_problem(&state.design);
assert!(text.starts_with("Degenerate"), "{text}");
assert!(is_problem);
}
#[test]
fn design_to_gpu_planes_inverts_the_halfspace_sign_convention() {
let design = indicatrix_cut_core::Design::fresh(
indicatrix_cut_core::PreformSpec::cylinder(12, 1.3, 1.0, 0.9),
12,
4,
1.6,
);
let original = design
.planes()
.expect("a fresh design has no tiers to anchor");
let converted = design_to_gpu_planes(&design);
assert_eq!(original.len(), converted.len());
for (&(n, m), gpu) in original.iter().zip(&converted) {
let (round_trip_n, round_trip_m) = gpu.to_halfspace_f64();
assert!(
(round_trip_n - n).length() < 1e-5,
"normal did not round-trip: {round_trip_n:?} vs {n:?}"
);
assert!(
(round_trip_m - m).abs() < 1e-5,
"offset did not round-trip: {round_trip_m} vs {m}"
);
}
}
#[test]
fn status_text_reports_the_girdle_diameter_remedy_for_an_unresolvable_depth_target() {
let mut state = EditorState::fresh();
state
.apply(Edit::AddTier {
index: 0,
tier: ConstraintTier {
angle_deg: 90.0,
name: "G".to_string(),
indices: vec![],
constraint: indicatrix::geometry::meet_solver::MeetConstraint::ScaleReference(1.0),
imported_meet: None,
original_notes: None,
detached: Vec::new(),
},
})
.unwrap();
state
.apply(Edit::SetTierTarget {
index: 0,
target: Some(TierTarget::DepthMm(3.2)),
})
.unwrap();
assert_eq!(
state.design.girdle_diameter_mm, None,
"this design must never have had a girdle diameter set, or the target \
would resolve instead of hitting the error this test checks"
);
let (text, is_problem) = status_text_and_is_problem(&state.design);
assert!(is_problem);
assert!(
text.contains("girdle diameter"),
"expected TargetResolveError::MissingGirdleDiameter's own remedy \
sentence in the status strip text, got: {text}"
);
}