@@ -125,6 +125,10 @@ async fn test_sorting() {
125125 for ( json, expect) in resp. iter ( ) . zip ( & expects) {
126126 assert_eq ! ( json. versions[ 0 ] . num, * expect) ;
127127 assert_eq ! ( json. meta. total as usize , expects. len( ) ) ;
128+ assert_eq ! (
129+ json. meta. release_tracks,
130+ Some ( json!( { "1.x" : { "highest" : "1.0.0" } } ) )
131+ ) ;
128132 }
129133 assert_eq ! ( calls as usize , expects. len( ) + 1 ) ;
130134}
@@ -211,6 +215,91 @@ async fn test_seek_based_pagination_semver_sorting() {
211215 assert_eq ! ( json. meta. release_tracks, release_tracks) ;
212216}
213217
218+ #[ tokio:: test( flavor = "multi_thread" ) ]
219+ async fn test_seek_based_pagination_date_sorting ( ) {
220+ let ( app, anon, user) = TestApp :: init ( ) . with_user ( ) ;
221+ let user = user. as_model ( ) ;
222+ app. db ( |conn| {
223+ CrateBuilder :: new ( "foo_versions" , user. id )
224+ . version ( VersionBuilder :: new ( "0.5.2" ) . yanked ( true ) )
225+ . version ( "0.5.1" )
226+ . version ( VersionBuilder :: new ( "1.0.0" ) . rust_version ( "1.64" ) )
227+ . version ( "0.5.0" )
228+ . expect_build ( conn) ;
229+ // Make version 1.0.0 mimic a version published before we started recording who published
230+ // versions
231+ let none: Option < i32 > = None ;
232+ update ( versions:: table)
233+ . filter ( versions:: num. eq ( "1.0.0" ) )
234+ . set ( versions:: published_by. eq ( none) )
235+ . execute ( conn)
236+ . unwrap ( ) ;
237+ } ) ;
238+
239+ let url = "/api/v1/crates/foo_versions/versions" ;
240+ let expects = [ "0.5.0" , "1.0.0" , "0.5.1" , "0.5.2" ] ;
241+ let release_tracks = Some ( json ! ( {
242+ "1.x" : { "highest" : "1.0.0" } ,
243+ "0.5" : { "highest" : "0.5.1" }
244+ } ) ) ;
245+
246+ // per_page larger than the number of versions
247+ let json: VersionList = anon
248+ . get_with_query ( url, "per_page=10&sort=date" )
249+ . await
250+ . good ( ) ;
251+ assert_eq ! ( nums( & json. versions) , expects) ;
252+ assert_eq ! ( json. meta. total as usize , expects. len( ) ) ;
253+ assert_eq ! ( json. meta. release_tracks, release_tracks) ;
254+
255+ let json: VersionList = anon
256+ . get_with_query ( url, "per_page=1&sort=date" )
257+ . await
258+ . good ( ) ;
259+ assert_eq ! ( nums( & json. versions) , expects[ 0 ..1 ] ) ;
260+ assert_eq ! ( json. meta. total as usize , expects. len( ) ) ;
261+
262+ let seek = json
263+ . meta
264+ . next_page
265+ . map ( |s| s. split_once ( "seek=" ) . unwrap ( ) . 1 . to_owned ( ) )
266+ . map ( |p| p. split_once ( '&' ) . map ( |t| t. 0 . to_owned ( ) ) . unwrap_or ( p) )
267+ . unwrap ( ) ;
268+
269+ // per_page larger than the number of remain versions
270+ let json: VersionList = anon
271+ . get_with_query ( url, & format ! ( "per_page=5&sort=date&seek={seek}" ) )
272+ . await
273+ . good ( ) ;
274+ assert_eq ! ( nums( & json. versions) , expects[ 1 ..] ) ;
275+ assert ! ( json. meta. next_page. is_none( ) ) ;
276+ assert_eq ! ( json. meta. total as usize , expects. len( ) ) ;
277+ assert_eq ! ( json. meta. release_tracks, release_tracks) ;
278+
279+ // per_page euqal to the number of remain versions
280+ let json: VersionList = anon
281+ . get_with_query ( url, & format ! ( "per_page=2&sort=date&seek={seek}" ) )
282+ . await
283+ . good ( ) ;
284+ assert_eq ! ( nums( & json. versions) , expects[ 1 ..3 ] ) ;
285+ assert ! ( json. meta. next_page. is_some( ) ) ;
286+ assert_eq ! ( json. meta. total as usize , expects. len( ) ) ;
287+ assert_eq ! ( json. meta. release_tracks, release_tracks) ;
288+
289+ // A decodable seek value, WzE3Mjg1NjE5OTI3MzQ2NzMsNV0K ([1728561992734673,5]), but doesn't actually exist
290+ let json: VersionList = anon
291+ . get_with_query (
292+ url,
293+ "per_page=10&sort=date&seek=WzE3Mjg1NjE5OTI3MzQ2NzMsNV0K" ,
294+ )
295+ . await
296+ . good ( ) ;
297+ assert_eq ! ( json. versions. len( ) , 0 ) ;
298+ assert ! ( json. meta. next_page. is_none( ) ) ;
299+ assert_eq ! ( json. meta. total, 0 ) ;
300+ assert_eq ! ( json. meta. release_tracks, release_tracks) ;
301+ }
302+
214303#[ tokio:: test( flavor = "multi_thread" ) ]
215304async fn invalid_seek_parameter ( ) {
216305 let ( app, anon, user) = TestApp :: init ( ) . with_user ( ) ;
0 commit comments