diff --git a/bobbin/crates/xrpc/src/lib.rs b/bobbin/crates/xrpc/src/lib.rs index e5e056236..7f7aec9e3 100644 --- a/bobbin/crates/xrpc/src/lib.rs +++ b/bobbin/crates/xrpc/src/lib.rs @@ -1831,10 +1831,15 @@ struct PageState { } pub(crate) fn paged_tail(cursor: Option, total: Option) -> Vec { - let encoded = serde_json::to_string(&cursor).unwrap_or_else(|_| "null".to_owned()); - match total { - Some(t) => format!("],\"cursor\":{encoded},\"total\":{}}}", t.get()).into_bytes(), - None => format!("],\"cursor\":{encoded}}}").into_bytes(), + let encoded = + cursor.map(|value| serde_json::to_string(&value).unwrap_or_else(|_| "\"\"".to_owned())); + match (encoded, total) { + (Some(cursor), Some(total)) => { + format!("],\"cursor\":{cursor},\"total\":{}}}", total.get()).into_bytes() + } + (Some(cursor), None) => format!("],\"cursor\":{cursor}}}").into_bytes(), + (None, Some(total)) => format!("],\"total\":{}}}", total.get()).into_bytes(), + (None, None) => unpaged_tail(), } } diff --git a/bobbin/crates/xrpc/tests/aggregation.rs b/bobbin/crates/xrpc/tests/aggregation.rs index 43cc18655..6b866cfe3 100644 --- a/bobbin/crates/xrpc/tests/aggregation.rs +++ b/bobbin/crates/xrpc/tests/aggregation.rs @@ -273,7 +273,7 @@ async fn list_issues_with_no_edges_returns_empty_items() { let (status, body) = json_response(resp).await; assert_eq!(status, StatusCode::OK); assert_eq!(body["items"], json!([])); - assert!(body["cursor"].is_null()); + assert!(body.get("cursor").is_none()); } #[tokio::test] @@ -584,7 +584,10 @@ async fn list_paginates_via_cursor() { .await; let page2_items = page2["items"].as_array().unwrap().clone(); assert_eq!(page2_items.len(), 3); - assert!(page2["cursor"].is_null(), "tail page must not promise more"); + assert!( + page2.get("cursor").is_none(), + "tail page must not promise more" + ); let union: Vec<&str> = page1_items .iter() @@ -717,7 +720,7 @@ async fn list_paginates_via_offset() { .await; assert_eq!(page["items"].as_array().unwrap().len(), 0); assert_eq!(page["total"], json!(5)); - assert!(page["cursor"].is_null()); + assert!(page.get("cursor").is_none()); } #[tokio::test] @@ -1956,7 +1959,7 @@ async fn list_after_remove_source_returns_empty_items() { .await; assert_eq!(status, StatusCode::OK); assert_eq!(body["items"], json!([])); - assert!(body["cursor"].is_null()); + assert!(body.get("cursor").is_none()); } #[tokio::test] diff --git a/bobbin/crates/xrpc/tests/search.rs b/bobbin/crates/xrpc/tests/search.rs index 019e44224..a50cc8d97 100644 --- a/bobbin/crates/xrpc/tests/search.rs +++ b/bobbin/crates/xrpc/tests/search.rs @@ -282,7 +282,7 @@ async fn empty_query_returns_no_hits() { let (status, body) = json_response(resp).await; assert_eq!(status, StatusCode::OK); assert_eq!(body["hits"], json!([])); - assert!(body["cursor"].is_null()); + assert!(body.get("cursor").is_none()); } #[tokio::test] @@ -510,7 +510,7 @@ async fn pagination_round_trips_via_cursor() { ) .await; assert_eq!(page3["hits"].as_array().unwrap().len(), 1); - assert!(page3["cursor"].is_null()); + assert!(page3.get("cursor").is_none()); } #[tokio::test]