test(api): cover search visibility-filter narrowing; note pagination cap rationale
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -79,6 +79,8 @@ pub(crate) async fn search_objects(
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Search uses a tighter default/cap (20, max 50) than the shared `Pagination`
|
||||||
|
// (default 50, max 200): result pages are slower to scan than a raw object list.
|
||||||
let offset = params.offset.unwrap_or(0).max(0) as usize;
|
let offset = params.offset.unwrap_or(0).max(0) as usize;
|
||||||
let limit = params.limit.unwrap_or(20).clamp(1, 50) as usize;
|
let limit = params.limit.unwrap_or(20).clamp(1, 50) as usize;
|
||||||
|
|
||||||
|
|||||||
@@ -189,6 +189,98 @@ async fn search_returns_results_and_validates_params(pool: PgPool) {
|
|||||||
assert_eq!(bad.status(), StatusCode::BAD_REQUEST);
|
assert_eq!(bad.status(), StatusCode::BAD_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[sqlx::test(migrations = "../db/migrations")]
|
||||||
|
async fn search_visibility_filter_narrows_results(pool: PgPool) {
|
||||||
|
migrate_sessions(&db::Db::from_pool(pool.clone()))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
seed_user(&pool, "ed@example.com", "pw-editor-123", Role::Editor).await;
|
||||||
|
|
||||||
|
let (url, key) = meili();
|
||||||
|
let search = SearchClient::connect(&url, &key, &unique_index()).unwrap();
|
||||||
|
|
||||||
|
search.ensure_index().await.unwrap();
|
||||||
|
|
||||||
|
let app = build_app(state(pool.clone(), Some(search)));
|
||||||
|
let cookie = login(&app, "ed@example.com", "pw-editor-123").await;
|
||||||
|
|
||||||
|
let create_internal = app
|
||||||
|
.clone()
|
||||||
|
.oneshot(
|
||||||
|
Request::builder()
|
||||||
|
.method("POST")
|
||||||
|
.uri("/api/admin/objects")
|
||||||
|
.header(header::COOKIE, &cookie)
|
||||||
|
.header(header::CONTENT_TYPE, "application/json")
|
||||||
|
.body(Body::from(
|
||||||
|
r#"{"object_number":"R-2","object_name":"astrolabe-internal","number_of_objects":1,"visibility":"internal"}"#,
|
||||||
|
))
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(create_internal.status(), StatusCode::CREATED);
|
||||||
|
|
||||||
|
let create_draft = app
|
||||||
|
.clone()
|
||||||
|
.oneshot(
|
||||||
|
Request::builder()
|
||||||
|
.method("POST")
|
||||||
|
.uri("/api/admin/objects")
|
||||||
|
.header(header::COOKIE, &cookie)
|
||||||
|
.header(header::CONTENT_TYPE, "application/json")
|
||||||
|
.body(Body::from(
|
||||||
|
r#"{"object_number":"R-3","object_name":"astrolabe-draft","number_of_objects":1,"visibility":"draft"}"#,
|
||||||
|
))
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(create_draft.status(), StatusCode::CREATED);
|
||||||
|
|
||||||
|
let all = app
|
||||||
|
.clone()
|
||||||
|
.oneshot(
|
||||||
|
Request::builder()
|
||||||
|
.uri("/api/admin/search?q=astrolabe")
|
||||||
|
.header(header::COOKIE, &cookie)
|
||||||
|
.body(Body::empty())
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(all.status(), StatusCode::OK);
|
||||||
|
|
||||||
|
let all_body: serde_json::Value =
|
||||||
|
serde_json::from_slice(&all.into_body().collect().await.unwrap().to_bytes()).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(all_body["estimated_total"], 2);
|
||||||
|
|
||||||
|
let filtered = app
|
||||||
|
.clone()
|
||||||
|
.oneshot(
|
||||||
|
Request::builder()
|
||||||
|
.uri("/api/admin/search?q=astrolabe&visibility=internal")
|
||||||
|
.header(header::COOKIE, &cookie)
|
||||||
|
.body(Body::empty())
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(filtered.status(), StatusCode::OK);
|
||||||
|
|
||||||
|
let filtered_body: serde_json::Value =
|
||||||
|
serde_json::from_slice(&filtered.into_body().collect().await.unwrap().to_bytes()).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(filtered_body["estimated_total"], 1);
|
||||||
|
assert_eq!(filtered_body["hits"][0]["visibility"], "internal");
|
||||||
|
}
|
||||||
|
|
||||||
#[sqlx::test(migrations = "../db/migrations")]
|
#[sqlx::test(migrations = "../db/migrations")]
|
||||||
async fn search_unavailable_when_not_configured(pool: PgPool) {
|
async fn search_unavailable_when_not_configured(pool: PgPool) {
|
||||||
migrate_sessions(&db::Db::from_pool(pool.clone()))
|
migrate_sessions(&db::Db::from_pool(pool.clone()))
|
||||||
|
|||||||
Reference in New Issue
Block a user