@@ -380,6 +380,82 @@ fn index_sorting() {
380
380
assert_eq ! ( resp[ 3 ] . meta. total, 4 ) ;
381
381
assert_eq ! ( calls, 5 ) ;
382
382
383
+ use std:: cmp:: Reverse ;
384
+
385
+ fn decode_seek < D : for < ' a > serde:: Deserialize < ' a > > ( seek : & str ) -> anyhow:: Result < D > {
386
+ use base64:: { engine:: general_purpose, Engine } ;
387
+ let decoded = serde_json:: from_slice ( & general_purpose:: URL_SAFE_NO_PAD . decode ( seek) ?) ?;
388
+ Ok ( decoded)
389
+ }
390
+
391
+ // Sort by alpha with query
392
+ for query in [ "sort=alpha&q=bar_sort" , "sort=alpha&q=sort" ] {
393
+ let ( resp, calls) = page_with_seek ( & anon, query) ;
394
+ assert_eq ! ( calls, resp[ 0 ] . meta. total + 1 ) ;
395
+ let decoded_seeks = resp
396
+ . iter ( )
397
+ . filter_map ( |cl| {
398
+ cl. meta
399
+ . next_page
400
+ . as_ref ( )
401
+ . map ( |next_page| ( next_page, cl. crates [ 0 ] . name . to_owned ( ) ) )
402
+ } )
403
+ . filter_map ( |( q, name) | {
404
+ let query = url:: form_urlencoded:: parse ( q. trim_start_matches ( '?' ) . as_bytes ( ) )
405
+ . into_owned ( )
406
+ . collect :: < indexmap:: IndexMap < String , String > > ( ) ;
407
+ query. get ( "seek" ) . map ( |s| {
408
+ let d = decode_seek :: < ( bool , i32 ) > ( s) . unwrap ( ) ;
409
+ ( d. 0 , name)
410
+ } )
411
+ } )
412
+ . collect :: < Vec < _ > > ( ) ;
413
+ // ordering (exact match desc, name asc)
414
+ let mut sorted = decoded_seeks. to_vec ( ) ;
415
+ sorted. sort_by_key ( |k| ( Reverse ( k. 0 ) , k. 1 . to_owned ( ) ) ) ;
416
+ assert_eq ! ( sorted, decoded_seeks) ;
417
+ for json in search_both ( & anon, query) {
418
+ assert_eq ! ( json. meta. total, resp[ 0 ] . meta. total) ;
419
+ for ( c, r) in json. crates . iter ( ) . zip ( & resp) {
420
+ assert_eq ! ( c. name, r. crates[ 0 ] . name) ;
421
+ }
422
+ }
423
+ }
424
+
425
+ // Sort by relevance
426
+ for query in [ "q=foo_sort" , "q=sort" ] {
427
+ let ( resp, calls) = page_with_seek ( & anon, query) ;
428
+ assert_eq ! ( calls, resp[ 0 ] . meta. total + 1 ) ;
429
+ let decoded_seeks = resp
430
+ . iter ( )
431
+ . filter_map ( |cl| {
432
+ cl. meta
433
+ . next_page
434
+ . as_ref ( )
435
+ . map ( |next_page| ( next_page, cl. crates [ 0 ] . name . to_owned ( ) ) )
436
+ } )
437
+ . filter_map ( |( q, name) | {
438
+ let query = url:: form_urlencoded:: parse ( q. trim_start_matches ( '?' ) . as_bytes ( ) )
439
+ . into_owned ( )
440
+ . collect :: < indexmap:: IndexMap < String , String > > ( ) ;
441
+ query. get ( "seek" ) . map ( |s| {
442
+ let d = decode_seek :: < ( bool , f32 , i32 ) > ( s) . unwrap ( ) ;
443
+ ( d. 0 , ( d. 1 * 1e12 ) as i64 , name)
444
+ } )
445
+ } )
446
+ . collect :: < Vec < _ > > ( ) ;
447
+ // ordering (exact match desc, rank desc, name asc)
448
+ let mut sorted = decoded_seeks. clone ( ) ;
449
+ sorted. sort_by_key ( |k| ( Reverse ( k. 0 ) , Reverse ( k. 1 ) , k. 2 . to_owned ( ) ) ) ;
450
+ assert_eq ! ( sorted, decoded_seeks) ;
451
+ for json in search_both ( & anon, query) {
452
+ assert_eq ! ( json. meta. total, resp[ 0 ] . meta. total) ;
453
+ for ( c, r) in json. crates . iter ( ) . zip ( & resp) {
454
+ assert_eq ! ( c. name, r. crates[ 0 ] . name) ;
455
+ }
456
+ }
457
+ }
458
+
383
459
// Test for bug with showing null results first when sorting
384
460
// by descending downloads
385
461
for json in search_both ( & anon, "sort=recent-downloads" ) {
0 commit comments