@@ -171,6 +171,18 @@ mod tests {
171171 assert ! ( !is_newer( "1.0.0" , "not-a-version" ) ) ;
172172 }
173173
174+ #[ test]
175+ fn test_is_newer_four_component ( ) {
176+ // pandas-stubs style: 3.0.0.260204 is newer than 3.0.0
177+ assert ! ( is_newer( "3.0.0.260204" , "3.0.0" ) ) ;
178+ // and newer than a prior 4-component release
179+ assert ! ( is_newer( "3.0.0.260204" , "3.0.0.250204" ) ) ;
180+ // same 4-component version is not newer
181+ assert ! ( !is_newer( "3.0.0.260204" , "3.0.0.260204" ) ) ;
182+ // older 4-component is not newer than current
183+ assert ! ( !is_newer( "3.0.0.250204" , "3.0.0.260204" ) ) ;
184+ }
185+
174186 #[ test]
175187 fn test_classify_bump_major ( ) {
176188 assert_eq ! ( classify_bump( "1.0.0" , "2.0.0" ) , BumpKind :: Major ) ;
@@ -188,6 +200,64 @@ mod tests {
188200 fn test_classify_bump_patch ( ) {
189201 assert_eq ! ( classify_bump( "1.0.0" , "1.0.1" ) , BumpKind :: Patch ) ;
190202 assert_eq ! ( classify_bump( "7.3.0" , "7.3.1" ) , BumpKind :: Patch ) ;
203+ // 4-component versions (e.g. pandas-stubs 3.0.0 → 3.0.0.260204)
204+ assert_eq ! ( classify_bump( "3.0.0" , "3.0.0.260204" ) , BumpKind :: Patch ) ;
205+ assert_eq ! (
206+ classify_bump( "3.0.0.250204" , "3.0.0.260204" ) ,
207+ BumpKind :: Patch
208+ ) ;
209+ }
210+
211+ #[ tokio:: test]
212+ async fn test_check_dep_four_component_update ( ) {
213+ // pandas-stubs pattern: current >=3.0.0, latest 3.0.0.260204
214+ use wiremock:: matchers:: { method, path} ;
215+ use wiremock:: { Mock , MockServer , ResponseTemplate } ;
216+
217+ let server = MockServer :: start ( ) . await ;
218+ Mock :: given ( method ( "GET" ) )
219+ . and ( path ( "/pypi/pandas-stubs/json" ) )
220+ . respond_with ( ResponseTemplate :: new ( 200 ) . set_body_json ( serde_json:: json!( {
221+ "info" : { "version" : "3.0.0.260204" }
222+ } ) ) )
223+ . mount ( & server)
224+ . await ;
225+
226+ let client = PypiClient :: with_base_url ( & server. uri ( ) ) . unwrap ( ) ;
227+ let dep = crate :: parsers:: Dependency {
228+ name : "pandas-stubs" . to_string ( ) ,
229+ constraint : ">=3.0.0" . to_string ( ) ,
230+ } ;
231+ let update = check_dep ( & client, & dep) . await . unwrap ( ) . unwrap ( ) ;
232+ assert_eq ! ( update. latest, "3.0.0.260204" ) ;
233+ assert_eq ! ( update. bump_kind, BumpKind :: Patch ) ;
234+ assert_eq ! ( update. updated_constraint, ">=3.0.0.260204" ) ;
235+ }
236+
237+ #[ tokio:: test]
238+ async fn test_check_dep_four_component_to_four_component ( ) {
239+ // pandas-stubs: current >=3.0.0.250204, latest 3.0.0.260204
240+ use wiremock:: matchers:: { method, path} ;
241+ use wiremock:: { Mock , MockServer , ResponseTemplate } ;
242+
243+ let server = MockServer :: start ( ) . await ;
244+ Mock :: given ( method ( "GET" ) )
245+ . and ( path ( "/pypi/pandas-stubs/json" ) )
246+ . respond_with ( ResponseTemplate :: new ( 200 ) . set_body_json ( serde_json:: json!( {
247+ "info" : { "version" : "3.0.0.260204" }
248+ } ) ) )
249+ . mount ( & server)
250+ . await ;
251+
252+ let client = PypiClient :: with_base_url ( & server. uri ( ) ) . unwrap ( ) ;
253+ let dep = crate :: parsers:: Dependency {
254+ name : "pandas-stubs" . to_string ( ) ,
255+ constraint : ">=3.0.0.250204" . to_string ( ) ,
256+ } ;
257+ let update = check_dep ( & client, & dep) . await . unwrap ( ) . unwrap ( ) ;
258+ assert_eq ! ( update. latest, "3.0.0.260204" ) ;
259+ assert_eq ! ( update. bump_kind, BumpKind :: Patch ) ;
260+ assert_eq ! ( update. updated_constraint, ">=3.0.0.260204" ) ;
191261 }
192262
193263 // check_dep and find_updates - network paths covered via wiremock.
0 commit comments