Files
hcie-rust-v3.05/hcie-iced-app/crates/hcie-iced-gui/tests/selection_test.rs
T
phantom 1240d25011 feat(gui): implement selection mask state and vector editing functionality
- Add `selection/state.rs` to manage selection masks, including combining masks and calculating bounds.
- Introduce `vector_edit.rs` for vector shape manipulation, handling drag sessions, and hit testing for handles.
- Create `feature_scorecard.rs` to ensure stable feature identifiers and regression gates for GUI components.
- Implement raster behavior tests in `raster_test.rs` to validate gradient application against masks.
2026-07-16 18:41:05 +03:00

125 lines
3.5 KiB
Rust

//! Tests for selection types: SelectionTransform, TransformHandle, CropState.
use hcie_iced_gui::selection::clipboard::centered_transform;
use hcie_iced_gui::selection::state::{combine_masks, mask_bounds, selected_spans};
use hcie_iced_gui::selection::{CropState, SelectionMode, SelectionTransform, TransformHandle};
#[test]
fn test_selection_transform_is_empty() {
let tr = SelectionTransform {
pixels: vec![],
width: 0,
height: 0,
pos: iced::Vector::ZERO,
size: iced::Vector::ZERO,
rotation: 0.0,
};
assert!(tr.is_empty());
}
#[test]
fn test_selection_transform_with_data() {
let tr = SelectionTransform {
pixels: vec![255; 100],
width: 5,
height: 5,
pos: iced::Vector::new(10.0, 20.0),
size: iced::Vector::new(5.0, 5.0),
rotation: 0.0,
};
assert!(!tr.is_empty());
}
#[test]
fn test_crop_state_lifecycle() {
let mut crop = CropState::default();
assert!(!crop.active);
assert!(crop.rect.is_none());
crop.start_drag(10.0, 10.0);
assert!(crop.active);
assert!(crop.is_dragging);
crop.update_drag(100.0, 100.0);
assert!(crop.rect.is_some());
let (x, y, w, h) = crop.rect.unwrap();
assert_eq!(x, 10.0);
assert_eq!(y, 10.0);
assert_eq!(w, 90.0);
assert_eq!(h, 90.0);
crop.end_drag();
assert!(!crop.is_dragging);
let result = crop.confirm();
assert!(result.is_some());
assert!(!crop.active);
}
#[test]
fn test_crop_cancel() {
let mut crop = CropState::default();
crop.start_drag(10.0, 10.0);
crop.update_drag(100.0, 100.0);
crop.cancel();
assert!(!crop.active);
assert!(crop.rect.is_none());
}
#[test]
fn test_transform_handle_cursor_hints() {
assert_eq!(TransformHandle::Move.cursor_hint(), "move");
assert_eq!(TransformHandle::TopLeft.cursor_hint(), "nwse-resize");
assert_eq!(TransformHandle::Rotate.cursor_hint(), "crosshair");
}
#[test]
fn selection_modes_combine_alpha_without_losing_soft_edges() {
let old = [0, 64, 255, 255];
let new = [255, 128, 64, 0];
assert_eq!(combine_masks(Some(&old), &new, SelectionMode::Replace), new);
assert_eq!(
combine_masks(Some(&old), &new, SelectionMode::Add),
[255, 128, 255, 255]
);
assert_eq!(
combine_masks(Some(&old), &new, SelectionMode::Subtract),
[0, 0, 191, 255]
);
assert_eq!(
combine_masks(Some(&old), &new, SelectionMode::Intersect),
[0, 64, 64, 0]
);
}
#[test]
fn irregular_mask_bounds_and_fill_spans_are_exact() {
let mask = [0, 255, 0, 0, 255, 255, 0, 0, 0, 255, 0, 0];
assert_eq!(mask_bounds(&mask, 4, 3), Some((0, 0, 2, 3)));
assert_eq!(
selected_spans(&mask, 4, 3),
vec![(1, 0, 2), (0, 1, 2), (1, 2, 2)]
);
}
#[test]
fn crop_clamps_drag_and_cancel_restores_idle_state() {
let mut crop = CropState::default();
crop.start_drag_clamped(-20.0, 5.0, 100, 80);
crop.update_drag(140.0, 120.0);
assert_eq!(crop.rect, Some((0.0, 5.0, 100.0, 75.0)));
crop.cancel();
assert_eq!(crop.canvas_size, None);
assert!(!crop.active);
}
#[test]
fn clipboard_transform_is_centered_and_transform_geometry_is_safe() {
let mut transform = centered_transform(vec![255; 8 * 4 * 4], 8, 4, 100, 50).unwrap();
assert_eq!(transform.pos, iced::Vector::new(46.0, 23.0));
transform.size = iced::Vector::new(-20.0, f32::NAN);
transform.sanitize_geometry(true);
assert!(transform.size.x > 0.0 && transform.size.y > 0.0);
assert!((transform.size.x / transform.size.y - 2.0).abs() < 0.001);
}