Repository: GraphiteEditor/Graphite
File: editor/src/messages/tool/transform_layer/transform_layer_message_handler.rs (Rust)

Code before:
				increments_key: Key::Control,
			})
			.await;

		let after_scale_transform = get_layer_transform(&mut editor, layer).await.unwrap();
		let before_scale_det = after_rotate_transform.matrix2.determinant();
		let after_scale_det = after_scale_transform.matrix2.determinant();
		assert!(
			after_scale_det >= 2.0 * before_scale_det,
			"Scale should increase the determinant of the matrix (before: {}, after: {})",
			before_scale_det,
			after_scale_det
		);

		editor.handle_message(TransformLayerMessage::ApplyTransformOperation { final_transform: true }).await;
		let final_transform = get_layer_transform(&mut editor, layer).await.unwrap();

		assert!(final_transform.abs_diff_eq(after_scale_transform, 1e-5), "Final transform should match the transform before committing");
		assert!(!final_transform.abs_diff_eq(original_transform, 1e-5), "Final transform should be different from original transform");
	}
	#[tokio::test]
	async fn test_grs_single_anchor() {
		let mut editor = EditorTestUtils::create();
		editor.new_document().await;
		editor.drag_tool(ToolType::Pen, 100., 100., 100., 100., ModifierKeys::empty()).await;
		editor.handle_message(ToolMessage::ActivateTool { tool_type: ToolType::Select }).await;

		// Testing grab operation - just checking that it doesn't crash
		editor.handle_message(TransformLayerMessage::BeginGrab).await;
		editor.move_mouse(150.0, 150.0, ModifierKeys::empty(), MouseKeys::NONE).await;
		editor
			.handle_message(TransformLayerMessage::PointerMove {
				slow_key: Key::Shift,
				increments_key: Key::Control,
			})
			.await;
		editor.handle_message(TransformLayerMessage::ApplyTransformOperation { final_transform: true }).await;

		let document = editor.active_document();
		let layer = document.metadata().all_layers().next().unwrap();
		let final_transform = get_layer_transform(&mut editor, layer).await;
		// Verifying a transform node was created
		assert!(final_transform.is_some(), "Transform node should exist after grab operation");
	}
}


Review comment (bug):
Whilst this does create a path with one point at the moment, this is a bug (I've now created an issue #2503).

If you create a layer, you can then add a path node with a single point with:
```rs
let modification_type = VectorModificationType::InsertPoint {
	id: PointId::generate(),
	position: DVec2::ZERO,
};
responses.add(GraphOperationMessage::Vector { layer, modification_type });
```

Code after:
			.handle_message(TransformLayerMessage::PointerMove {
				slow_key: Key::Shift,
				increments_key: Key::Control,
			})
			.await;

		let after_scale_transform = get_layer_transform(&mut editor, layer).await.unwrap();
		let before_scale_det = after_rotate_transform.matrix2.determinant();
		let after_scale_det = after_scale_transform.matrix2.determinant();
		assert!(
			after_scale_det >= 2.0 * before_scale_det,
			"Scale should increase the determinant of the matrix (before: {}, after: {})",
			before_scale_det,
			after_scale_det
		);

		editor.handle_message(TransformLayerMessage::ApplyTransformOperation { final_transform: true }).await;
		let final_transform = get_layer_transform(&mut editor, layer).await.unwrap();

		assert!(final_transform.abs_diff_eq(after_scale_transform, 1e-5), "Final transform should match the transform before committing");
		assert!(!final_transform.abs_diff_eq(original_transform, 1e-5), "Final transform should be different from original transform");
	}

	#[tokio::test]
	async fn test_scale_with_panned_view() {
		let mut editor = EditorTestUtils::create();
		editor.new_document().await;
		editor.drag_tool(ToolType::Rectangle, 0., 0., 100., 100., ModifierKeys::empty()).await;
		let document = editor.active_document();
		let layer = document.metadata().all_layers().next().unwrap();

		let original_transform = get_layer_transform(&mut editor, layer).await.unwrap();

		let pan_amount = DVec2::new(200.0, 150.0);
		editor.handle_message(NavigationMessage::CanvasPan { delta: pan_amount }).await;

		editor.handle_message(TransformLayerMessage::BeginScale).await;
		editor.handle_message(TransformLayerMessage::TypeDigit { digit: 2 }).await;
		editor.handle_message(TransformLayerMessage::ApplyTransformOperation { final_transform: true }).await;

		let final_transform = get_layer_transform(&mut editor, layer).await.unwrap();

		let scale_x = final_transform.matrix2.x_axis.length() / original_transform.matrix2.x_axis.length();
		let scale_y = final_transform.matrix2.y_axis.length() / original_transform.matrix2.y_axis.length();

		assert!((scale_x - 2.0).abs() < 0.1, "Expected scale factor X of 2.0, got: {}", scale_x);
		assert!((scale_y - 2.0).abs() < 0.1, "Expected scale factor Y of 2.0, got: {}", scale_y);
	}

	#[tokio::test]
	async fn test_scale_with_zoomed_view() {