11"""Test cases for the Spiral model."""
22
33import datetime
4+ from typing import Dict , cast
45
56import pandas as pd
67import pytest
@@ -137,6 +138,108 @@ def test_path_optimality_non_positive_distance() -> None:
137138 assert segment .path_optimality == 0.0
138139
139140
141+ @pytest .mark .parametrize (
142+ "points_data,start_params,end_params,expected_start,expected_end,test_id" ,
143+ [
144+ (
145+ {"x" : [0 , 1 , 2 , 3 , 4 , 5 ], "y" : [0 , 1 , 2 , 3 , 4 , 5 ]},
146+ {"order" : 1 , "label" : "A" , "center_x" : 0 , "center_y" : 0 , "radius" : 0.5 },
147+ {"order" : 2 , "label" : "B" , "center_x" : 5 , "center_y" : 5 , "radius" : 0.5 },
148+ 1 ,
149+ 5 ,
150+ "valid_trajectory" ,
151+ ),
152+ (
153+ {"x" : [0.1 , 0.2 , 0.3 ], "y" : [0.1 , 0.2 , 0.3 ]},
154+ {"order" : 1 , "label" : "A" , "center_x" : 0 , "center_y" : 0 , "radius" : 1.0 },
155+ {"order" : 2 , "label" : "B" , "center_x" : 10 , "center_y" : 10 , "radius" : 1.0 },
156+ None ,
157+ None ,
158+ "no_exit_from_start" ,
159+ ),
160+ (
161+ {"x" : [0 , 1 , 2 , 3 ], "y" : [0 , 1 , 2 , 3 ]},
162+ {"order" : 1 , "label" : "A" , "center_x" : 0 , "center_y" : 0 , "radius" : 0.5 },
163+ {"order" : 2 , "label" : "B" , "center_x" : 10 , "center_y" : 10 , "radius" : 0.5 },
164+ 1 ,
165+ None ,
166+ "never_reaches_end" ,
167+ ),
168+ (
169+ {"x" : [], "y" : []},
170+ {"order" : 1 , "label" : "A" , "center_x" : 0 , "center_y" : 0 , "radius" : 1.0 },
171+ {"order" : 2 , "label" : "B" , "center_x" : 5 , "center_y" : 5 , "radius" : 1.0 },
172+ None ,
173+ None ,
174+ "empty_dataframe" ,
175+ ),
176+ (
177+ {"x" : [0.1 ], "y" : [0.1 ]},
178+ {"order" : 1 , "label" : "A" , "center_x" : 0 , "center_y" : 0 , "radius" : 1.0 },
179+ {"order" : 2 , "label" : "B" , "center_x" : 5 , "center_y" : 5 , "radius" : 1.0 },
180+ None ,
181+ None ,
182+ "single_point_in_start" ,
183+ ),
184+ (
185+ {"x" : [2 ], "y" : [2 ]},
186+ {"order" : 1 , "label" : "A" , "center_x" : 0 , "center_y" : 0 , "radius" : 0.5 },
187+ {"order" : 2 , "label" : "B" , "center_x" : 5 , "center_y" : 5 , "radius" : 0.5 },
188+ 0 ,
189+ None ,
190+ "single_point_outside_start" ,
191+ ),
192+ (
193+ {"x" : [0 , 2.5 , 5 ], "y" : [0 , 2.5 , 5 ]},
194+ {"order" : 1 , "label" : "A" , "center_x" : 0 , "center_y" : 0 , "radius" : 0.5 },
195+ {"order" : 2 , "label" : "B" , "center_x" : 2.5 , "center_y" : 2.5 , "radius" : 1.0 },
196+ 1 ,
197+ 1 ,
198+ "immediate_transition" ,
199+ ),
200+ (
201+ {"x" : [3 , 4 , 5 ], "y" : [3 , 4 , 5 ]},
202+ {"order" : 1 , "label" : "A" , "center_x" : 0 , "center_y" : 0 , "radius" : 0.5 },
203+ {"order" : 2 , "label" : "B" , "center_x" : 5 , "center_y" : 5 , "radius" : 0.5 },
204+ 0 ,
205+ 2 ,
206+ "first_point_outside_start" ,
207+ ),
208+ ],
209+ ids = lambda x : x if isinstance (x , str ) else "" ,
210+ )
211+ def test_valid_ink_trajectory (
212+ points_data : Dict [str , list [float ]],
213+ start_params : dict [str , int | str | float ],
214+ end_params : dict [str , int | str | float ],
215+ expected_start : int | None ,
216+ expected_end : int | None ,
217+ test_id : str ,
218+ ) -> None :
219+ """Test valid_ink_trajectory method with various point configurations.
220+
221+ Tests behavior with different circle boundaries.
222+ """
223+ points_df = pd .DataFrame (points_data )
224+
225+ start_circle = models .CircleTarget (** start_params ) # type: ignore[arg-type]
226+ end_circle = models .CircleTarget (** end_params ) # type: ignore[arg-type]
227+
228+ line_segment = models .LineSegment (
229+ start_label = cast (str , start_params ["label" ]),
230+ end_label = cast (str , end_params ["label" ]),
231+ points = points_df ,
232+ is_error = False ,
233+ line_number = 1 ,
234+ )
235+ result_start , result_end = line_segment .valid_ink_trajectory (
236+ start_circle , end_circle
237+ )
238+
239+ assert result_start == expected_start , f"Start index mismatch for { test_id } "
240+ assert result_end == expected_end , f"End index mismatch for { test_id } "
241+
242+
140243def test_uniform_motion () -> None :
141244 """Test with points moving at constant velocity."""
142245 points = pd .DataFrame ({
@@ -148,10 +251,6 @@ def test_uniform_motion() -> None:
148251 start_label = "1" ,
149252 end_label = "2" ,
150253 points = points ,
151- is_error = False ,
152- line_number = 1 ,
153- )
154-
155254 segment .calculate_velocity_metrics (points )
156255
157256 assert segment .distance == pytest .approx (3.0 )
@@ -270,3 +369,4 @@ def test_stationary_motion() -> None:
270369 assert all (v == pytest .approx (0.0 ) for v in segment .velocities )
271370 assert len (segment .accelerations ) == 1
272371 assert segment .accelerations [0 ] == pytest .approx (0.0 )
372+
0 commit comments