diff --git a/server/tests/adresar/get_adresar_by_position_test.rs b/server/tests/adresar/get_adresar_by_position_test.rs index e26d7a6..86d9e6d 100644 --- a/server/tests/adresar/get_adresar_by_position_test.rs +++ b/server/tests/adresar/get_adresar_by_position_test.rs @@ -1,7 +1,7 @@ // tests/adresar/get_adresar_by_position_test.rs use rstest::{fixture, rstest}; -use server::adresar::handlers::get_adresar_by_position; -use common::proto::multieko2::common::PositionRequest; +use server::adresar::handlers::{get_adresar_by_position, get_adresar_count}; +use common::proto::multieko2::common::{PositionRequest, Empty}; use crate::common::setup_test_db; use sqlx::PgPool; use tonic; @@ -58,14 +58,14 @@ async fn find_position_of_record(pool: &PgPool, id: i64) -> Option { .fetch_all(pool) .await .unwrap(); - + // Find the position of our record (1-based) for (index, record_id) in records.iter().enumerate() { if *record_id == id { return Some((index + 1) as i64); } } - + None } @@ -74,11 +74,11 @@ async fn find_position_of_record(pool: &PgPool, id: i64) -> Option { #[tokio::test] async fn test_position_zero(#[future] pool: PgPool) { let pool = pool.await; - + // Request position 0 (invalid) let request = PositionRequest { position: 0 }; let result = get_adresar_by_position(&pool, request).await; - + // Verify it returns an error assert!(result.is_err()); assert_eq!(result.unwrap_err().code(), tonic::Code::InvalidArgument); @@ -88,11 +88,11 @@ async fn test_position_zero(#[future] pool: PgPool) { #[tokio::test] async fn test_position_negative(#[future] pool: PgPool) { let pool = pool.await; - + // Request negative position (invalid) let request = PositionRequest { position: -1 }; let result = get_adresar_by_position(&pool, request).await; - + // Verify it returns an error assert!(result.is_err()); assert_eq!(result.unwrap_err().code(), tonic::Code::InvalidArgument); @@ -102,36 +102,36 @@ async fn test_position_negative(#[future] pool: PgPool) { #[tokio::test] async fn test_basic_position_retrieval(#[future] pool: PgPool) { let pool = pool.await; - + // Take a lock to prevent concurrent test execution let _guard = TEST_MUTEX.lock().await; - + // Use a unique prefix for test data to prevent conflicts let prefix = "PosBasicTest"; - + // Clean up any existing test data cleanup_test_records(&pool, prefix).await; - + // Create test records let id1 = create_test_record(&pool, &format!("{}_1", prefix), false).await; let id2 = create_test_record(&pool, &format!("{}_2", prefix), false).await; let id3 = create_test_record(&pool, &format!("{}_3", prefix), false).await; - + // Find the positions of these records in the database let pos1 = find_position_of_record(&pool, id1).await.unwrap(); let pos2 = find_position_of_record(&pool, id2).await.unwrap(); let pos3 = find_position_of_record(&pool, id3).await.unwrap(); - + // Test retrieving each position let response1 = get_adresar_by_position(&pool, PositionRequest { position: pos1 }).await.unwrap(); assert_eq!(response1.id, id1); - + let response2 = get_adresar_by_position(&pool, PositionRequest { position: pos2 }).await.unwrap(); assert_eq!(response2.id, id2); - + let response3 = get_adresar_by_position(&pool, PositionRequest { position: pos3 }).await.unwrap(); assert_eq!(response3.id, id3); - + // Clean up test data cleanup_test_records(&pool, prefix).await; } @@ -140,35 +140,35 @@ async fn test_basic_position_retrieval(#[future] pool: PgPool) { #[tokio::test] async fn test_deleted_records_excluded(#[future] pool: PgPool) { let pool = pool.await; - + // Take a lock to prevent concurrent test execution let _guard = TEST_MUTEX.lock().await; - + // Use a unique prefix for test data let prefix = "PosDeletedTest"; - + // Clean up any existing test data cleanup_test_records(&pool, prefix).await; - + // Create a mix of active and deleted records let id1 = create_test_record(&pool, &format!("{}_1", prefix), false).await; let _id_deleted = create_test_record(&pool, &format!("{}_del", prefix), true).await; let id2 = create_test_record(&pool, &format!("{}_2", prefix), false).await; - + // Find positions let pos1 = find_position_of_record(&pool, id1).await.unwrap(); let pos2 = find_position_of_record(&pool, id2).await.unwrap(); - + // Verify positions are consecutive, which means the deleted record is excluded assert_eq!(pos2, pos1 + 1); - + // Retrieve by position and verify let response1 = get_adresar_by_position(&pool, PositionRequest { position: pos1 }).await.unwrap(); assert_eq!(response1.id, id1); - + let response2 = get_adresar_by_position(&pool, PositionRequest { position: pos2 }).await.unwrap(); assert_eq!(response2.id, id2); - + // Clean up test data cleanup_test_records(&pool, prefix).await; } @@ -177,44 +177,44 @@ async fn test_deleted_records_excluded(#[future] pool: PgPool) { #[tokio::test] async fn test_position_changes_after_deletion(#[future] pool: PgPool) { let pool = pool.await; - + // Take a lock to prevent concurrent test execution let _guard = TEST_MUTEX.lock().await; - + // Use a unique prefix for test data let prefix = "PosChangeTest"; - + // Clean up any existing test data cleanup_test_records(&pool, prefix).await; - + // Create records let id1 = create_test_record(&pool, &format!("{}_1", prefix), false).await; let id2 = create_test_record(&pool, &format!("{}_2", prefix), false).await; let id3 = create_test_record(&pool, &format!("{}_3", prefix), false).await; - + // Find initial positions - let pos1 = find_position_of_record(&pool, id1).await.unwrap(); + let _pos1 = find_position_of_record(&pool, id1).await.unwrap(); let pos2 = find_position_of_record(&pool, id2).await.unwrap(); let pos3 = find_position_of_record(&pool, id3).await.unwrap(); - + // Mark the first record as deleted sqlx::query!("UPDATE adresar SET deleted = TRUE WHERE id = $1", id1) .execute(&pool) .await .unwrap(); - + // Find new positions let pos2_after = find_position_of_record(&pool, id2).await.unwrap(); let pos3_after = find_position_of_record(&pool, id3).await.unwrap(); - + // Verify positions shifted assert!(pos2_after < pos2); assert!(pos3_after < pos3); - + // Verify by retrieving records at new positions let response_at_first = get_adresar_by_position(&pool, PositionRequest { position: pos2_after }).await.unwrap(); assert_eq!(response_at_first.id, id2); - + // Clean up test data cleanup_test_records(&pool, prefix).await; } @@ -223,10 +223,10 @@ async fn test_position_changes_after_deletion(#[future] pool: PgPool) { #[tokio::test] async fn test_position_out_of_bounds(#[future] pool: PgPool) { let pool = pool.await; - + // Take a lock to prevent concurrent test execution let _guard = TEST_MUTEX.lock().await; - + // Get the total count of non-deleted records let count = sqlx::query_scalar!( "SELECT COUNT(*) FROM adresar WHERE deleted = FALSE" @@ -235,11 +235,11 @@ async fn test_position_out_of_bounds(#[future] pool: PgPool) { .await .unwrap() .unwrap_or(0); - + // Request a position beyond the count let request = PositionRequest { position: count + 1 }; let result = get_adresar_by_position(&pool, request).await; - + // Verify it returns an error assert!(result.is_err()); assert_eq!(result.unwrap_err().code(), tonic::Code::NotFound); @@ -249,11 +249,11 @@ async fn test_position_out_of_bounds(#[future] pool: PgPool) { #[tokio::test] async fn test_database_error(#[future] closed_pool: PgPool) { let closed_pool = closed_pool.await; - + // Attempt to query with a closed pool let request = PositionRequest { position: 1 }; let result = get_adresar_by_position(&closed_pool, request).await; - + // Verify it returns an internal error assert!(result.is_err()); assert_eq!(result.unwrap_err().code(), tonic::Code::Internal); @@ -263,41 +263,106 @@ async fn test_database_error(#[future] closed_pool: PgPool) { #[tokio::test] async fn test_position_after_adding_record(#[future] pool: PgPool) { let pool = pool.await; - + // Take a lock to prevent concurrent test execution let _guard = TEST_MUTEX.lock().await; - + // Use a unique prefix for test data let prefix = "PosAddTest"; - + // Clean up any existing test data cleanup_test_records(&pool, prefix).await; - + // Create records let id1 = create_test_record(&pool, &format!("{}_1", prefix), false).await; let id2 = create_test_record(&pool, &format!("{}_2", prefix), false).await; - + // Find positions let pos1 = find_position_of_record(&pool, id1).await.unwrap(); let pos2 = find_position_of_record(&pool, id2).await.unwrap(); - + // Add a new record let id3 = create_test_record(&pool, &format!("{}_3", prefix), false).await; - + // Find its position let pos3 = find_position_of_record(&pool, id3).await.unwrap(); - + // Verify retrieval by position let response3 = get_adresar_by_position(&pool, PositionRequest { position: pos3 }).await.unwrap(); assert_eq!(response3.id, id3); - + // Verify original positions still work let response1 = get_adresar_by_position(&pool, PositionRequest { position: pos1 }).await.unwrap(); assert_eq!(response1.id, id1); - + let response2 = get_adresar_by_position(&pool, PositionRequest { position: pos2 }).await.unwrap(); assert_eq!(response2.id, id2); - + + // Clean up test data + cleanup_test_records(&pool, prefix).await; +} + +/// Test handler correctly excludes deleted records +#[rstest] +#[tokio::test] +async fn test_handler_excludes_deleted_records(#[future] pool: PgPool) { + let pool = pool.await; + + // Take a lock to prevent concurrent test execution + let _guard = TEST_MUTEX.lock().await; + + // Use a unique prefix for test data + let prefix = "CountTest"; + + // Clean up any existing test data + cleanup_test_records(&pool, prefix).await; + + // Create active records + for i in 1..=3 { + create_test_record(&pool, &format!("{}_Active_{}", prefix, i), false).await; + } + + // Create deleted records + for i in 1..=2 { + create_test_record(&pool, &format!("{}_Deleted_{}", prefix, i), true).await; + } + + // Count our test records by deleted status + let active_test_count = sqlx::query_scalar!( + "SELECT COUNT(*) FROM adresar WHERE firma LIKE $1 AND deleted = FALSE", + format!("{}%", prefix) + ) + .fetch_one(&pool) + .await + .unwrap() + .unwrap_or(0); + + let deleted_test_count = sqlx::query_scalar!( + "SELECT COUNT(*) FROM adresar WHERE firma LIKE $1 AND deleted = TRUE", + format!("{}%", prefix) + ) + .fetch_one(&pool) + .await + .unwrap() + .unwrap_or(0); + + // Verify our test data was inserted correctly + assert_eq!(active_test_count, 3); + assert_eq!(deleted_test_count, 2); + + // Get the total count of active records (including existing ones) + let total_active_count = sqlx::query_scalar!( + "SELECT COUNT(*) FROM adresar WHERE deleted = FALSE" + ) + .fetch_one(&pool) + .await + .unwrap() + .unwrap_or(0); + + // Now call our handler and verify it returns the same count + let response = get_adresar_count(&pool, Empty {}).await.unwrap(); + assert_eq!(response.count, total_active_count); + // Clean up test data cleanup_test_records(&pool, prefix).await; }