Skip to content

Commit 73d12bc

Browse files
Add tests for Spline tool to support continuing a previously drawn spline (#2591)
* Add tests for Spline tool to support continuing a previously drawn spline * refactor
1 parent 0877c75 commit 73d12bc

File tree

2 files changed

+124
-0
lines changed

2 files changed

+124
-0
lines changed

editor/src/messages/tool/tool_messages/spline_tool.rs

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,3 +534,118 @@ fn delete_preview(tool_data: &mut SplineToolData, responses: &mut VecDeque<Messa
534534
tool_data.preview_point = None;
535535
tool_data.preview_segment = None;
536536
}
537+
538+
#[cfg(test)]
539+
mod test_spline_tool {
540+
use crate::messages::tool::tool_messages::spline_tool::find_spline;
541+
use crate::test_utils::test_prelude::*;
542+
use glam::DAffine2;
543+
use graphene_core::vector::VectorData;
544+
use graphene_std::vector::PointId;
545+
546+
fn assert_point_positions(vector_data: &VectorData, layer_to_viewport: DAffine2, expected_points: &[DVec2], epsilon: f64) {
547+
let points_in_viewport: Vec<DVec2> = vector_data
548+
.point_domain
549+
.ids()
550+
.iter()
551+
.filter_map(|&point_id| {
552+
let position = vector_data.point_domain.position_from_id(point_id)?;
553+
Some(layer_to_viewport.transform_point2(position))
554+
})
555+
.collect();
556+
557+
// Verify each point position is close to the expected position
558+
for (i, expected_point) in expected_points.iter().enumerate() {
559+
let actual_point = points_in_viewport[i];
560+
let distance = (actual_point - *expected_point).length();
561+
562+
assert!(
563+
distance < epsilon,
564+
"Point {} position mismatch: expected {:?}, got {:?} (distance: {})",
565+
i,
566+
expected_point,
567+
actual_point,
568+
distance
569+
);
570+
}
571+
}
572+
573+
#[tokio::test]
574+
async fn test_continue_drawing_from_existing_spline() {
575+
let mut editor = EditorTestUtils::create();
576+
editor.new_document().await;
577+
578+
let initial_points = [DVec2::new(100., 100.), DVec2::new(200., 150.), DVec2::new(300., 100.)];
579+
580+
editor.select_tool(ToolType::Spline).await;
581+
582+
for &point in &initial_points {
583+
editor.click_tool(ToolType::Spline, MouseKeys::LEFT, point, ModifierKeys::empty()).await;
584+
}
585+
586+
editor.press(Key::Enter, ModifierKeys::empty()).await;
587+
588+
let document = editor.active_document();
589+
let spline_layer = document
590+
.metadata()
591+
.all_layers()
592+
.find(|layer| find_spline(document, *layer).is_some())
593+
.expect("Failed to find a layer with a spline node");
594+
595+
let first_spline_node = find_spline(document, spline_layer).expect("Spline node not found in the layer");
596+
597+
let first_vector_data = document.network_interface.compute_modified_vector(spline_layer).expect("Vector data not found for the spline layer");
598+
599+
// Verify initial spline has correct number of points and segments
600+
let initial_point_count = first_vector_data.point_domain.ids().len();
601+
let initial_segment_count = first_vector_data.segment_domain.ids().len();
602+
assert_eq!(initial_point_count, 3, "Expected 3 points in initial spline, found {}", initial_point_count);
603+
assert_eq!(initial_segment_count, 2, "Expected 2 segments in initial spline, found {}", initial_segment_count);
604+
605+
let layer_to_viewport = document.metadata().transform_to_viewport(spline_layer);
606+
607+
let endpoints: Vec<(PointId, DVec2)> = first_vector_data
608+
.extendable_points(false)
609+
.filter_map(|point_id| first_vector_data.point_domain.position_from_id(point_id).map(|pos| (point_id, layer_to_viewport.transform_point2(pos))))
610+
.collect();
611+
612+
assert_eq!(endpoints.len(), 2, "Expected 2 endpoints in the initial spline");
613+
614+
let (_, endpoint_position) = endpoints.first().expect("No endpoints found in spline");
615+
616+
editor.select_tool(ToolType::Spline).await;
617+
editor.click_tool(ToolType::Spline, MouseKeys::LEFT, *endpoint_position, ModifierKeys::empty()).await;
618+
619+
let continuation_points = [DVec2::new(400., 150.), DVec2::new(500., 100.)];
620+
621+
for &point in &continuation_points {
622+
editor.click_tool(ToolType::Spline, MouseKeys::LEFT, point, ModifierKeys::empty()).await;
623+
}
624+
625+
editor.press(Key::Enter, ModifierKeys::empty()).await;
626+
627+
let document = editor.active_document();
628+
let extended_vector_data = document
629+
.network_interface
630+
.compute_modified_vector(spline_layer)
631+
.expect("Vector data not found for the extended spline layer");
632+
633+
// Verify extended spline has correct number of points and segments
634+
let extended_point_count = extended_vector_data.point_domain.ids().len();
635+
let extended_segment_count = extended_vector_data.segment_domain.ids().len();
636+
637+
assert_eq!(extended_point_count, 5, "Expected 5 points in extended spline, found {}", extended_point_count);
638+
assert_eq!(extended_segment_count, 4, "Expected 4 segments in extended spline, found {}", extended_segment_count);
639+
640+
// Verify the spline node is still the same
641+
let extended_spline_node = find_spline(document, spline_layer).expect("Spline node not found after extension");
642+
assert_eq!(first_spline_node, extended_spline_node, "Spline node changed after extension");
643+
644+
// Verify the positions of all points in the extended spline
645+
let layer_to_viewport = document.metadata().transform_to_viewport(spline_layer);
646+
647+
let all_expected_points = [initial_points[0], initial_points[1], initial_points[2], continuation_points[0], continuation_points[1]];
648+
649+
assert_point_positions(&extended_vector_data, layer_to_viewport, &all_expected_points, 1e-10);
650+
}
651+
}

editor/src/test_utils.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,15 @@ impl EditorTestUtils {
230230
})
231231
.await;
232232
}
233+
pub async fn draw_spline(&mut self, points: &[DVec2]) {
234+
self.select_tool(ToolType::Spline).await;
235+
236+
for &point in points {
237+
self.click_tool(ToolType::Spline, MouseKeys::LEFT, point, ModifierKeys::empty()).await;
238+
}
239+
240+
self.press(Key::Enter, ModifierKeys::empty()).await;
241+
}
233242
}
234243

235244
pub trait FrontendMessageTestUtils {

0 commit comments

Comments
 (0)