Skip to content

Commit be2d3da

Browse files
committed
fixup! tests/routes/crates/list: Ensure unique ordering of seek-based pagination is correct
1 parent f312a08 commit be2d3da

File tree

1 file changed

+76
-0
lines changed

1 file changed

+76
-0
lines changed

src/tests/routes/crates/list.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,82 @@ fn index_sorting() {
380380
assert_eq!(resp[3].meta.total, 4);
381381
assert_eq!(calls, 5);
382382

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+
383459
// Test for bug with showing null results first when sorting
384460
// by descending downloads
385461
for json in search_both(&anon, "sort=recent-downloads") {

0 commit comments

Comments
 (0)