2026-07-21 04:25:23 +03:00
|
|
|
//! Regression coverage for atomic vector-shape creation history.
|
|
|
|
|
//!
|
|
|
|
|
//! **Purpose:** Ensures the first vector shape and its auto-created vector layer form one exact
|
|
|
|
|
//! Undo/Redo transaction, while later shapes on the same layer continue to use vector snapshots.
|
|
|
|
|
//! **Logic & Workflow:** Creates shapes through the public `Engine` API, inspects history metadata,
|
|
|
|
|
//! and exercises Undo/Redo against layer and shape counts.
|
|
|
|
|
//! **Side Effects / Dependencies:** Uses only in-memory engine documents.
|
|
|
|
|
|
|
|
|
|
use hcie_engine_api::{Engine, LayerType, VectorShape};
|
|
|
|
|
|
|
|
|
|
/// Builds a deterministic rectangle for history tests.
|
|
|
|
|
///
|
|
|
|
|
/// **Arguments:** `offset` shifts the rectangle so repeated shapes remain distinct.
|
|
|
|
|
/// **Returns:** A filled vector rectangle with stable styling.
|
|
|
|
|
/// **Side Effects / Dependencies:** None.
|
|
|
|
|
fn rectangle(offset: f32) -> VectorShape {
|
|
|
|
|
VectorShape::Rect {
|
|
|
|
|
name: String::new(),
|
|
|
|
|
x1: 10.0 + offset,
|
|
|
|
|
y1: 12.0 + offset,
|
|
|
|
|
x2: 60.0 + offset,
|
|
|
|
|
y2: 48.0 + offset,
|
|
|
|
|
stroke: 2.0,
|
|
|
|
|
color: [10, 20, 30, 255],
|
|
|
|
|
fill: true,
|
|
|
|
|
fill_color: [40, 50, 60, 255],
|
|
|
|
|
radius: 0.0,
|
|
|
|
|
angle: 0.0,
|
|
|
|
|
opacity: 1.0,
|
|
|
|
|
hardness: 0.5,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn first_vector_shape_is_one_atomic_layer_transaction() {
|
|
|
|
|
let mut engine = Engine::new(128, 96);
|
|
|
|
|
let layers_before = engine.get_layer_count();
|
|
|
|
|
let history_before = engine.history_len();
|
|
|
|
|
|
|
|
|
|
engine.add_vector_shape(rectangle(0.0));
|
|
|
|
|
|
|
|
|
|
assert_eq!(engine.get_layer_count(), layers_before + 1);
|
|
|
|
|
assert_eq!(engine.history_len(), history_before + 1);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
engine.history_description(history_before).as_deref(),
|
2026-07-23 02:28:49 +03:00
|
|
|
Some("Add Vector Shape (Rect)")
|
2026-07-21 04:25:23 +03:00
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
engine
|
|
|
|
|
.get_layer_info(engine.active_layer_id())
|
|
|
|
|
.map(|info| info.layer_type),
|
|
|
|
|
Some(LayerType::Vector)
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
engine.active_vector_shapes().map(|shapes| shapes.len()),
|
|
|
|
|
Some(1)
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
assert!(engine.undo());
|
|
|
|
|
assert_eq!(engine.get_layer_count(), layers_before);
|
|
|
|
|
|
|
|
|
|
assert!(engine.redo());
|
|
|
|
|
assert_eq!(engine.get_layer_count(), layers_before + 1);
|
|
|
|
|
assert!(engine
|
|
|
|
|
.layer_infos()
|
|
|
|
|
.iter()
|
|
|
|
|
.any(|info| info.layer_type == LayerType::Vector && info.shape_count == 1));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn later_vector_shapes_each_add_one_snapshot() {
|
|
|
|
|
let mut engine = Engine::new(128, 96);
|
|
|
|
|
engine.add_vector_shape(rectangle(0.0));
|
|
|
|
|
let history_before = engine.history_len();
|
|
|
|
|
|
|
|
|
|
engine.add_vector_shape(rectangle(8.0));
|
|
|
|
|
|
|
|
|
|
assert_eq!(engine.history_len(), history_before + 1);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
engine.active_vector_shapes().map(|shapes| shapes.len()),
|
|
|
|
|
Some(2)
|
|
|
|
|
);
|
|
|
|
|
assert!(engine.undo());
|
|
|
|
|
assert_eq!(
|
|
|
|
|
engine.active_vector_shapes().map(|shapes| shapes.len()),
|
|
|
|
|
Some(1)
|
|
|
|
|
);
|
|
|
|
|
assert!(engine.redo());
|
|
|
|
|
assert_eq!(
|
|
|
|
|
engine.active_vector_shapes().map(|shapes| shapes.len()),
|
|
|
|
|
Some(2)
|
|
|
|
|
);
|
|
|
|
|
}
|