From 8605c446c58e973245e941da2919aa0abb8cc38f Mon Sep 17 00:00:00 2001 From: lauraaruon-cyber Date: Wed, 24 Jun 2026 14:30:17 +0700 Subject: [PATCH] test: Add REST tests for explicitly-retired / non-active lifecycle records (search) (Fixes #105) Implements integration tests mirroring the supersession tests to verify that search results correctly hide explicitly retired or non-active lifecycle status records by default, and correctly surface them when `include_retired=true`. --- .../lance-context-server/src/routes/search.rs | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/crates/lance-context-server/src/routes/search.rs b/crates/lance-context-server/src/routes/search.rs index a4f2d5d..9cd5515 100644 --- a/crates/lance-context-server/src/routes/search.rs +++ b/crates/lance-context-server/src/routes/search.rs @@ -292,6 +292,86 @@ mod tests { assert!(results.iter().any(|r| r.record.id == old_id)); } + #[tokio::test] + async fn search_respects_explicit_retirement() { + let (state, _dir) = test_state().await; + + let mut record = embedded_record("Explicit retire", [1.0, 0.0, 0.0]); + record.external_id = Some("doc-2".to_string()); + add(&state, vec![record]).await; + + // Patch to retired_at + let patch_req = UpdateRecordRequest { + id: None, + external_id: Some("doc-2".to_string()), + patch: RecordPatchDto { + retired_at: Some(Some(Utc::now())), + ..Default::default() + }, + }; + crate::routes::records::update_record( + axum::extract::State(state.clone()), + axum::extract::Path("test-ctx".to_string()), + axum::Json(patch_req), + ) + .await + .unwrap(); + + // Default search hides the retired record. + let results = run_search(&state, search_for([1.0, 0.0, 0.0])).await; + assert_eq!(results.len(), 0); + + // include_retired surfaces it. + let mut req = search_for([1.0, 0.0, 0.0]); + req.include_retired = true; + let results = run_search(&state, req).await; + assert_eq!(results.len(), 1); + assert_eq!( + results[0].record.text_payload.as_deref(), + Some("Explicit retire") + ); + } + + #[tokio::test] + async fn search_respects_non_active_lifecycle_status() { + let (state, _dir) = test_state().await; + + let mut record = embedded_record("Non-active", [1.0, 0.0, 0.0]); + record.external_id = Some("doc-3".to_string()); + add(&state, vec![record]).await; + + // Patch to contradicted + let patch_req = UpdateRecordRequest { + id: None, + external_id: Some("doc-3".to_string()), + patch: RecordPatchDto { + lifecycle_status: Some(Some(crate::model::LifecycleStatus::Contradicted)), + ..Default::default() + }, + }; + crate::routes::records::update_record( + axum::extract::State(state.clone()), + axum::extract::Path("test-ctx".to_string()), + axum::Json(patch_req), + ) + .await + .unwrap(); + + // Default search hides the contradicted record. + let results = run_search(&state, search_for([1.0, 0.0, 0.0])).await; + assert_eq!(results.len(), 0); + + // include_retired surfaces it. + let mut req = search_for([1.0, 0.0, 0.0]); + req.include_retired = true; + let results = run_search(&state, req).await; + assert_eq!(results.len(), 1); + assert_eq!( + results[0].record.text_payload.as_deref(), + Some("Non-active") + ); + } + #[tokio::test] async fn search_include_relationships_toggles_relationship_payload() { let (state, _dir) = test_state().await;