diff --git a/server/tests/adresar/delete_adresar_test.rs b/server/tests/adresar/delete_adresar_test.rs deleted file mode 100644 index 7524e7b..0000000 --- a/server/tests/adresar/delete_adresar_test.rs +++ /dev/null @@ -1,161 +0,0 @@ -// tests/adresar/delete_adresar_test.rs -use rstest::{fixture, rstest}; -use server::adresar::handlers::delete_adresar; -use common::proto::multieko2::adresar::DeleteAdresarRequest; -use crate::common::setup_test_db; -use sqlx::PgPool; -use tonic; -use std::sync::Arc; -use tokio::sync::Mutex; - -// Reuse the mutex from get_adresar_by_position_test or create a new one -lazy_static::lazy_static! { - static ref TEST_MUTEX: Arc> = Arc::new(Mutex::new(())); -} - -// Fixtures -#[fixture] -async fn pool() -> PgPool { - setup_test_db().await -} - -#[fixture] -async fn closed_pool(#[future] pool: PgPool) -> PgPool { - let pool = pool.await; - pool.close().await; - pool -} - -#[fixture] -async fn existing_record(#[future] pool: PgPool) -> (PgPool, i64, String) { - let pool = pool.await; - // Use a unique prefix for test data - let prefix = format!("DeleteTest_{}", chrono::Utc::now().timestamp_nanos_opt().unwrap_or_default()); - - let record = sqlx::query!( - r#" - INSERT INTO adresar (firma, deleted) - VALUES ($1, false) - RETURNING id - "#, - format!("{}_Company", prefix) - ) - .fetch_one(&pool) - .await - .unwrap(); - - (pool, record.id, prefix) -} - -#[fixture] -async fn existing_deleted_record(#[future] pool: PgPool) -> (PgPool, i64, String) { - let pool = pool.await; - // Use a unique prefix for test data - let prefix = format!("DeletedTest_{}", chrono::Utc::now().timestamp_nanos_opt().unwrap_or_default()); - - let record = sqlx::query!( - r#" - INSERT INTO adresar (firma, deleted) - VALUES ($1, true) - RETURNING id - "#, - format!("{}_Deleted", prefix) - ) - .fetch_one(&pool) - .await - .unwrap(); - - (pool, record.id, prefix) -} - -// Helper to check if the record is deleted -async fn assert_record_deleted(pool: &PgPool, id: i64) { - let db_record = sqlx::query!("SELECT deleted FROM adresar WHERE id = $1", id) - .fetch_one(pool) - .await - .unwrap(); - - assert!(db_record.deleted); -} - -// Helper to clean up test records -async fn cleanup_test_records(pool: &PgPool, prefix: &str) { - if !prefix.is_empty() { - sqlx::query!( - "DELETE FROM adresar WHERE firma LIKE $1", - format!("{}%", prefix) - ) - .execute(pool) - .await - .unwrap(); - } -} - -// Tests -#[rstest] -#[tokio::test] -async fn test_delete_adresar_success( - #[future] existing_record: (PgPool, i64, String), -) { - // Take a lock to prevent concurrent test execution - let _guard = TEST_MUTEX.lock().await; - - let (pool, id, prefix) = existing_record.await; - let request = DeleteAdresarRequest { id }; - let response = delete_adresar(&pool, request).await.unwrap(); - - assert!(response.success); - assert_record_deleted(&pool, id).await; - - // Clean up - cleanup_test_records(&pool, &prefix).await; -} - -#[rstest] -#[tokio::test] -async fn test_delete_adresar_nonexistent_id( - #[future] pool: PgPool, -) { - // Take a lock to prevent concurrent test execution - let _guard = TEST_MUTEX.lock().await; - - let pool = pool.await; - let request = DeleteAdresarRequest { id: 9999 }; - let response = delete_adresar(&pool, request).await.unwrap(); - - // Deleting a non-existent record should return success: false - assert!(!response.success); -} - -#[rstest] -#[tokio::test] -async fn test_delete_adresar_already_deleted( - #[future] existing_deleted_record: (PgPool, i64, String), -) { - // Take a lock to prevent concurrent test execution - let _guard = TEST_MUTEX.lock().await; - - let (pool, id, prefix) = existing_deleted_record.await; - let request = DeleteAdresarRequest { id }; - let response = delete_adresar(&pool, request).await.unwrap(); - - // Deleting an already deleted record should return success: false - assert!(!response.success); - - // Clean up - cleanup_test_records(&pool, &prefix).await; -} - -#[rstest] -#[tokio::test] -async fn test_delete_adresar_database_error( - #[future] closed_pool: PgPool, -) { - // No need for mutex here as we're not modifying the database - let closed_pool = closed_pool.await; - let request = DeleteAdresarRequest { id: 1 }; - let result = delete_adresar(&closed_pool, request).await; - - assert!(result.is_err()); - assert_eq!(result.unwrap_err().code(), tonic::Code::Internal); -} diff --git a/server/tests/adresar/get_adresar_by_position_test.rs b/server/tests/adresar/get_adresar_by_position_test.rs deleted file mode 100644 index 86d9e6d..0000000 --- a/server/tests/adresar/get_adresar_by_position_test.rs +++ /dev/null @@ -1,368 +0,0 @@ -// tests/adresar/get_adresar_by_position_test.rs -use rstest::{fixture, rstest}; -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; -use std::sync::Arc; -use tokio::sync::Mutex; - -// Use a global mutex to synchronize test execution -// This prevents tests from interfering with each other -lazy_static::lazy_static! { - static ref TEST_MUTEX: Arc> = Arc::new(Mutex::new(())); -} - -#[fixture] -async fn pool() -> PgPool { - setup_test_db().await -} - -#[fixture] -async fn closed_pool(#[future] pool: PgPool) -> PgPool { - let pool = pool.await; - pool.close().await; - pool -} - -// Create a test record with specific data and delete status -async fn create_test_record(pool: &PgPool, firma: &str, deleted: bool) -> i64 { - sqlx::query_scalar!( - "INSERT INTO adresar (firma, deleted) VALUES ($1, $2) RETURNING id", - firma, - deleted - ) - .fetch_one(pool) - .await - .unwrap() -} - -// Clean up test records after tests -async fn cleanup_test_records(pool: &PgPool, prefix: &str) { - sqlx::query!( - "DELETE FROM adresar WHERE firma LIKE $1", - format!("{}%", prefix) - ) - .execute(pool) - .await - .unwrap(); -} - -// Find the position of a record in the database -async fn find_position_of_record(pool: &PgPool, id: i64) -> Option { - // Get all non-deleted records ordered by ID - let records = sqlx::query_scalar!( - "SELECT id FROM adresar WHERE deleted = FALSE ORDER BY id ASC" - ) - .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 -} - -// Test position validation -#[rstest] -#[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); -} - -#[rstest] -#[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); -} - -#[rstest] -#[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; -} - -#[rstest] -#[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; -} - -#[rstest] -#[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 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; -} - -#[rstest] -#[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" - ) - .fetch_one(&pool) - .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); -} - -#[rstest] -#[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); -} - -#[rstest] -#[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; -} diff --git a/server/tests/adresar/get_adresar_count_test.rs b/server/tests/adresar/get_adresar_count_test.rs deleted file mode 100644 index c73e6df..0000000 --- a/server/tests/adresar/get_adresar_count_test.rs +++ /dev/null @@ -1,284 +0,0 @@ -// tests/adresar/get_adresar_count_test.rs -use rstest::{fixture, rstest}; -use server::adresar::handlers::get_adresar_count; -use common::proto::multieko2::common::Empty; -use crate::common::setup_test_db; -use sqlx::PgPool; -use tonic; - -// For connection pooling -#[fixture] -async fn pool() -> PgPool { - setup_test_db().await -} - -#[fixture] -async fn closed_pool(#[future] pool: PgPool) -> PgPool { - let pool = pool.await; - pool.close().await; - pool -} - -// Create a self-contained test that runs in a transaction -// -------------------------------------------------------- -// Instead of relying on table state and doing our own transaction management, -// we'll mock the database response to `get_adresar_count` and verify it behaves correctly - -/// Test only that the handler returns the value from the database correctly -#[rstest] -#[tokio::test] -async fn test_handler_returns_count_from_database(#[future] pool: PgPool) { - let pool = pool.await; - - // First, get whatever count the database currently has - let count_query = 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, count_query); -} - -/// Test handler correctly excludes deleted records -#[rstest] -#[tokio::test] -async fn test_handler_excludes_deleted_records(#[future] pool: PgPool) { - let pool = pool.await; - - // Use a transaction to isolate this test completely - let mut tx = pool.begin().await.unwrap(); - - // Count records where deleted = TRUE - let deleted_count = sqlx::query_scalar!( - "SELECT COUNT(*) FROM adresar WHERE deleted = TRUE" - ) - .fetch_one(&mut *tx) - .await - .unwrap() - .unwrap_or(0); - - // Count records where deleted = FALSE - let active_count = sqlx::query_scalar!( - "SELECT COUNT(*) FROM adresar WHERE deleted = FALSE" - ) - .fetch_one(&mut *tx) - .await - .unwrap() - .unwrap_or(0); - - // Count all records - let total_count = sqlx::query_scalar!( - "SELECT COUNT(*) FROM adresar" - ) - .fetch_one(&mut *tx) - .await - .unwrap() - .unwrap_or(0); - - // Verify our counts are consistent - assert_eq!(total_count, active_count + deleted_count); - - // Verify our handler returns only the active count - let response = get_adresar_count(&pool, Empty {}).await.unwrap(); - assert_eq!(response.count, active_count); - - // Rollback transaction - tx.rollback().await.unwrap(); -} - -/// Test SQL query behavior with deleted flag -#[rstest] -#[tokio::test] -async fn test_deleted_flag_filters_records(#[future] pool: PgPool) { - let pool = pool.await; - - // Use a transaction to isolate this test completely - let mut tx = pool.begin().await.unwrap(); - - // Insert test records inside this transaction - // They will be automatically rolled back at the end - - sqlx::query!( - "INSERT INTO adresar (firma, deleted) VALUES ($1, FALSE)", - "Test Active Record" - ) - .execute(&mut *tx) - .await - .unwrap(); - - sqlx::query!( - "INSERT INTO adresar (firma, deleted) VALUES ($1, TRUE)", - "Test Deleted Record" - ) - .execute(&mut *tx) - .await - .unwrap(); - - // Count active records in the transaction - let active_count = sqlx::query_scalar!( - "SELECT COUNT(*) FROM adresar WHERE deleted = FALSE" - ) - .fetch_one(&mut *tx) - .await - .unwrap() - .unwrap_or(0); - - // Count deleted records in the transaction - let deleted_count = sqlx::query_scalar!( - "SELECT COUNT(*) FROM adresar WHERE deleted = TRUE" - ) - .fetch_one(&mut *tx) - .await - .unwrap() - .unwrap_or(0); - - // Verify at least one active and one deleted record - assert!(active_count > 0); - assert!(deleted_count > 0); - - // Rollback transaction - tx.rollback().await.unwrap(); -} - -/// Test the handler returns an error with a closed pool -#[rstest] -#[tokio::test] -async fn test_database_error(#[future] closed_pool: PgPool) { - let closed_pool = closed_pool.await; - let result = get_adresar_count(&closed_pool, Empty {}).await; - assert!(result.is_err()); - assert_eq!(result.unwrap_err().code(), tonic::Code::Internal); -} - -/// Test the behavior of setting deleted to true and back -#[rstest] -#[tokio::test] -async fn test_update_of_deleted_flag(#[future] pool: PgPool) { - let pool = pool.await; - - // Use a transaction for complete isolation - let mut tx = pool.begin().await.unwrap(); - - // Insert a test record - let id = sqlx::query_scalar!( - "INSERT INTO adresar (firma, deleted) VALUES ($1, FALSE) RETURNING id", - "Test Toggle Record" - ) - .fetch_one(&mut *tx) - .await - .unwrap(); - - // Count active records with this new record - let active_count_before = sqlx::query_scalar!( - "SELECT COUNT(*) FROM adresar WHERE deleted = FALSE" - ) - .fetch_one(&mut *tx) - .await - .unwrap() - .unwrap_or(0); - - // Mark as deleted - sqlx::query!( - "UPDATE adresar SET deleted = TRUE WHERE id = $1", - id - ) - .execute(&mut *tx) - .await - .unwrap(); - - // Count active records after marking as deleted - let active_count_after_delete = sqlx::query_scalar!( - "SELECT COUNT(*) FROM adresar WHERE deleted = FALSE" - ) - .fetch_one(&mut *tx) - .await - .unwrap() - .unwrap_or(0); - - // Verify count decreased by 1 - assert_eq!(active_count_after_delete, active_count_before - 1); - - // Mark as active again - sqlx::query!( - "UPDATE adresar SET deleted = FALSE WHERE id = $1", - id - ) - .execute(&mut *tx) - .await - .unwrap(); - - // Count active records after marking as active - let active_count_after_restore = sqlx::query_scalar!( - "SELECT COUNT(*) FROM adresar WHERE deleted = FALSE" - ) - .fetch_one(&mut *tx) - .await - .unwrap() - .unwrap_or(0); - - // Verify count increased back to original - assert_eq!(active_count_after_restore, active_count_before); - - // Rollback transaction - tx.rollback().await.unwrap(); -} - -/// Test edge cases of an empty table -#[rstest] -#[tokio::test] -async fn test_edge_case_empty_table(#[future] pool: PgPool) { - let pool = pool.await; - - // Not literally testing an empty table since we can't truncate due to FK constraints - // But we can verify the count response is never negative - let response = get_adresar_count(&pool, Empty {}).await.unwrap(); - assert!(response.count >= 0); -} - -/// Test adding a record and verifying count increases -#[rstest] -#[tokio::test] -async fn test_count_increments_after_adding_record(#[future] pool: PgPool) { - let pool = pool.await; - - // Use a transaction for complete isolation - let mut tx = pool.begin().await.unwrap(); - - // Get initial active count inside transaction - let initial_count = sqlx::query_scalar!( - "SELECT COUNT(*) FROM adresar WHERE deleted = FALSE" - ) - .fetch_one(&mut *tx) - .await - .unwrap() - .unwrap_or(0); - - // Add a record inside the transaction - sqlx::query!( - "INSERT INTO adresar (firma, deleted) VALUES ($1, FALSE)", - "Test Increment Record" - ) - .execute(&mut *tx) - .await - .unwrap(); - - // Get new count inside transaction - let new_count = sqlx::query_scalar!( - "SELECT COUNT(*) FROM adresar WHERE deleted = FALSE" - ) - .fetch_one(&mut *tx) - .await - .unwrap() - .unwrap_or(0); - - // Verify count increased by exactly 1 - assert_eq!(new_count, initial_count + 1); - - // Rollback transaction - tx.rollback().await.unwrap(); -} diff --git a/server/tests/adresar/get_adresar_test.rs b/server/tests/adresar/get_adresar_test.rs deleted file mode 100644 index 6fdec08..0000000 --- a/server/tests/adresar/get_adresar_test.rs +++ /dev/null @@ -1,238 +0,0 @@ -// tests/adresar/get_adresar_test.rs -use rstest::{fixture, rstest}; -use server::adresar::handlers::get_adresar; -use common::proto::multieko2::adresar::{GetAdresarRequest, AdresarResponse}; -use crate::common::setup_test_db; -use sqlx::PgPool; -use tonic; - -#[fixture] -async fn pool() -> PgPool { - setup_test_db().await -} - -#[fixture] -async fn closed_pool(#[future] pool: PgPool) -> PgPool { - let pool = pool.await; - pool.close().await; - pool -} - -#[fixture] -async fn existing_record(#[future] pool: PgPool) -> (PgPool, i64) { - let pool = pool.await; - let record = sqlx::query!( - r#" - INSERT INTO adresar ( - firma, kz, drc, ulica, psc, mesto, stat, banka, ucet, - skladm, ico, kontakt, telefon, skladu, fax, deleted - ) - VALUES ( - 'Test Company', 'KZ', 'DRC', 'Street', '12345', 'City', - 'Country', 'Bank', 'Account', 'SkladM', 'ICO', 'Contact', - '+421123456789', 'SkladU', 'Fax', false - ) - RETURNING id - "# - ) - .fetch_one(&pool) - .await - .unwrap(); - - (pool, record.id) -} - -#[fixture] -async fn existing_deleted_record(#[future] pool: PgPool) -> (PgPool, i64) { - let pool = pool.await; - let record = sqlx::query!( - r#" - INSERT INTO adresar (firma, deleted) - VALUES ('Deleted Company', true) - RETURNING id - "# - ) - .fetch_one(&pool) - .await - .unwrap(); - - (pool, record.id) -} - -#[fixture] -async fn existing_record_with_nulls(#[future] pool: PgPool) -> (PgPool, i64) { - let pool = pool.await; - let record = sqlx::query!( - r#" - INSERT INTO adresar (firma) - VALUES ('Null Fields Company') - RETURNING id - "# - ) - .fetch_one(&pool) - .await - .unwrap(); - - (pool, record.id) -} - -async fn assert_response_matches(pool: &PgPool, id: i64, response: &AdresarResponse) { - let db_record = sqlx::query!("SELECT * FROM adresar WHERE id = $1", id) - .fetch_one(pool) - .await - .unwrap(); - - assert_eq!(db_record.firma, response.firma); - assert_eq!(db_record.kz.unwrap_or_default(), response.kz); - assert_eq!(db_record.drc.unwrap_or_default(), response.drc); - assert_eq!(db_record.ulica.unwrap_or_default(), response.ulica); - assert_eq!(db_record.psc.unwrap_or_default(), response.psc); - assert_eq!(db_record.mesto.unwrap_or_default(), response.mesto); - assert_eq!(db_record.stat.unwrap_or_default(), response.stat); - assert_eq!(db_record.banka.unwrap_or_default(), response.banka); - assert_eq!(db_record.ucet.unwrap_or_default(), response.ucet); - assert_eq!(db_record.skladm.unwrap_or_default(), response.skladm); - assert_eq!(db_record.ico.unwrap_or_default(), response.ico); - assert_eq!(db_record.kontakt.unwrap_or_default(), response.kontakt); - assert_eq!(db_record.telefon.unwrap_or_default(), response.telefon); - assert_eq!(db_record.skladu.unwrap_or_default(), response.skladu); - assert_eq!(db_record.fax.unwrap_or_default(), response.fax); -} - -#[rstest] -#[tokio::test] -async fn test_get_adresar_success( - #[future] existing_record: (PgPool, i64), -) { - let (pool, id) = existing_record.await; - let request = GetAdresarRequest { id }; - let response = get_adresar(&pool, request).await.unwrap(); - - assert_eq!(response.id, id); - assert_response_matches(&pool, id, &response).await; -} - -#[rstest] -#[tokio::test] -async fn test_get_optional_fields_null( - #[future] existing_record_with_nulls: (PgPool, i64), -) { - let (pool, id) = existing_record_with_nulls.await; - let request = GetAdresarRequest { id }; - let response = get_adresar(&pool, request).await.unwrap(); - - assert_eq!(response.kz, ""); - assert_eq!(response.drc, ""); - assert_eq!(response.ulica, ""); - assert_eq!(response.psc, ""); - assert_eq!(response.mesto, ""); - assert_eq!(response.stat, ""); - assert_eq!(response.banka, ""); - assert_eq!(response.ucet, ""); - assert_eq!(response.skladm, ""); - assert_eq!(response.ico, ""); - assert_eq!(response.kontakt, ""); - assert_eq!(response.telefon, ""); - assert_eq!(response.skladu, ""); - assert_eq!(response.fax, ""); -} - -#[rstest] -#[tokio::test] -async fn test_get_nonexistent_id( - #[future] pool: PgPool, -) { - let pool = pool.await; - let request = GetAdresarRequest { id: 9999 }; - let result = get_adresar(&pool, request).await; - - assert!(result.is_err()); - assert_eq!(result.unwrap_err().code(), tonic::Code::NotFound); -} - -#[rstest] -#[tokio::test] -async fn test_get_deleted_record( - #[future] existing_deleted_record: (PgPool, i64), -) { - let (pool, id) = existing_deleted_record.await; - let request = GetAdresarRequest { id }; - let result = get_adresar(&pool, request).await; - - assert!(result.is_err()); - assert_eq!(result.unwrap_err().code(), tonic::Code::NotFound); -} - -#[rstest] -#[tokio::test] -async fn test_database_error( - #[future] closed_pool: PgPool, -) { - let closed_pool = closed_pool.await; - let request = GetAdresarRequest { id: 1 }; - let result = get_adresar(&closed_pool, request).await; - - assert!(result.is_err()); - assert_eq!(result.unwrap_err().code(), tonic::Code::Internal); -} - -#[rstest] -#[tokio::test] -async fn test_get_special_characters( - #[future] pool: PgPool, -) { - let pool = pool.await; - let firma = "Náměstí ČR"; - let telefon = "+420 123-456.789"; - let ulica = "Křižíkova 123"; - - let record = sqlx::query!( - r#" - INSERT INTO adresar (firma, telefon, ulica) - VALUES ($1, $2, $3) - RETURNING id - "#, - firma, - telefon, - ulica - ) - .fetch_one(&pool) - .await - .unwrap(); - - let request = GetAdresarRequest { id: record.id }; - let response = get_adresar(&pool, request).await.unwrap(); - - assert_eq!(response.firma, firma); - assert_eq!(response.telefon, telefon); - assert_eq!(response.ulica, ulica); -} - -#[rstest] -#[tokio::test] -async fn test_get_max_length_fields( - #[future] pool: PgPool, -) { - let pool = pool.await; - let firma = "a".repeat(255); - let telefon = "1".repeat(20); - - let record = sqlx::query!( - r#" - INSERT INTO adresar (firma, telefon) - VALUES ($1, $2) - RETURNING id - "#, - firma, - telefon - ) - .fetch_one(&pool) - .await - .unwrap(); - - let request = GetAdresarRequest { id: record.id }; - let response = get_adresar(&pool, request).await.unwrap(); - - assert_eq!(response.firma.len(), 255); - assert_eq!(response.telefon.len(), 20); -} diff --git a/server/tests/adresar/mod.rs b/server/tests/adresar/mod.rs deleted file mode 100644 index 4ee661b..0000000 --- a/server/tests/adresar/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -// server/tests/adresar/mod.rs - -pub mod post_adresar_test; -pub mod put_adresar_test; -pub mod get_adresar_test; -pub mod get_adresar_count_test; -pub mod get_adresar_by_position_test; -pub mod delete_adresar_test; diff --git a/server/tests/adresar/post_adresar_test.rs b/server/tests/adresar/post_adresar_test.rs deleted file mode 100644 index 7b8e0c6..0000000 --- a/server/tests/adresar/post_adresar_test.rs +++ /dev/null @@ -1,222 +0,0 @@ -// tests/adresar/post_adresar_test.rs -use rstest::{fixture, rstest}; -use server::adresar::handlers::post_adresar; -use common::proto::multieko2::adresar::PostAdresarRequest; -use crate::common::setup_test_db; -use sqlx::PgPool; -use tonic; - -// Fixtures -#[fixture] -async fn pool() -> PgPool { - setup_test_db().await -} - -#[fixture] -async fn closed_pool(#[future] pool: PgPool) -> PgPool { - let pool = pool.await; - pool.close().await; - pool -} - -#[fixture] -fn valid_request() -> PostAdresarRequest { - PostAdresarRequest { - firma: "Test Company".into(), - kz: "KZ123".into(), - drc: "DRC456".into(), - ulica: "Test Street".into(), - psc: "12345".into(), - mesto: "Test City".into(), - stat: "Test Country".into(), - banka: "Test Bank".into(), - ucet: "123456789".into(), - skladm: "Warehouse M".into(), - ico: "12345678".into(), - kontakt: "John Doe".into(), - telefon: "+421123456789".into(), - skladu: "Warehouse U".into(), - fax: "+421123456700".into(), - } -} - -#[fixture] -fn minimal_request() -> PostAdresarRequest { - PostAdresarRequest { - firma: "Required Only".into(), - ..Default::default() - } -} - -// Helper to check database state -async fn assert_response_matches(pool: &PgPool, response: &common::proto::multieko2::adresar::AdresarResponse) { - let db_record = sqlx::query!("SELECT * FROM adresar WHERE id = $1", response.id) - .fetch_one(pool) - .await - .unwrap(); - - assert_eq!(db_record.firma, response.firma); - assert_eq!(db_record.telefon.as_deref(), Some(response.telefon.as_str())); - // Add assertions for other fields... - assert!(!db_record.deleted); - assert!(db_record.created_at.is_some()); -} - -// Tests -#[rstest] -#[tokio::test] -async fn test_create_adresar_success(#[future] pool: PgPool, valid_request: PostAdresarRequest) { - let pool = pool.await; - let response = post_adresar(&pool, valid_request).await.unwrap(); - - assert!(response.id > 0); - assert_eq!(response.firma, "Test Company"); - assert_response_matches(&pool, &response).await; -} - -#[rstest] -#[tokio::test] -async fn test_create_adresar_whitespace_trimming( - #[future] pool: PgPool, - valid_request: PostAdresarRequest, -) { - let pool = pool.await; - let mut request = valid_request; - request.firma = " Test Company ".into(); - request.telefon = " +421123456789 ".into(); - request.ulica = " Test Street ".into(); - - let response = post_adresar(&pool, request).await.unwrap(); - assert_eq!(response.firma, "Test Company"); - assert_eq!(response.telefon, "+421123456789"); - assert_eq!(response.ulica, "Test Street"); -} - -#[rstest] -#[tokio::test] -async fn test_create_adresar_empty_optional_fields( - #[future] pool: PgPool, - valid_request: PostAdresarRequest, -) { - let pool = pool.await; - let mut request = valid_request; - request.telefon = " ".into(); - - let response = post_adresar(&pool, request).await.unwrap(); - let db_telefon = sqlx::query_scalar!("SELECT telefon FROM adresar WHERE id = $1", response.id) - .fetch_one(&pool) - .await - .unwrap(); - - assert!(db_telefon.is_none()); - assert_eq!(response.telefon, ""); -} - -#[rstest] -#[tokio::test] -async fn test_create_adresar_invalid_firma( - #[future] pool: PgPool, - valid_request: PostAdresarRequest, -) { - let pool = pool.await; - let mut request = valid_request; - request.firma = " ".into(); - let result = post_adresar(&pool, request).await; - - assert!(result.is_err()); - assert_eq!(result.unwrap_err().code(), tonic::Code::InvalidArgument); -} - -#[rstest] -#[tokio::test] -async fn test_create_adresar_minimal_valid_request( - #[future] pool: PgPool, - minimal_request: PostAdresarRequest, -) { - let pool = pool.await; - let response = post_adresar(&pool, minimal_request).await.unwrap(); - - assert!(response.id > 0); - assert_eq!(response.firma, "Required Only"); - assert!(response.kz.is_empty()); - assert!(response.drc.is_empty()); -} - -#[rstest] -#[tokio::test] -async fn test_create_adresar_empty_firma( - #[future] pool: PgPool, - minimal_request: PostAdresarRequest, -) { - let pool = pool.await; - let mut request = minimal_request; - request.firma = "".into(); - let result = post_adresar(&pool, request).await; - - assert!(result.is_err()); - assert_eq!(result.unwrap_err().code(), tonic::Code::InvalidArgument); -} - -#[rstest] -#[tokio::test] -async fn test_create_adresar_database_error( - #[future] closed_pool: PgPool, - minimal_request: PostAdresarRequest, -) { - let closed_pool = closed_pool.await; - let result = post_adresar(&closed_pool, minimal_request).await; - - assert!(result.is_err()); - assert_eq!(result.unwrap_err().code(), tonic::Code::Internal); -} - -#[rstest] -#[tokio::test] -async fn test_create_adresar_field_length_limits( - #[future] pool: PgPool, - valid_request: PostAdresarRequest, -) { - let pool = pool.await; - let mut request = valid_request; - request.firma = "a".repeat(255); - request.telefon = "1".repeat(20); - - let response = post_adresar(&pool, request).await.unwrap(); - assert_eq!(response.firma.len(), 255); - assert_eq!(response.telefon.len(), 20); -} - -#[rstest] -#[tokio::test] -async fn test_create_adresar_special_characters( - #[future] pool: PgPool, - valid_request: PostAdresarRequest, -) { - let pool = pool.await; - let mut request = valid_request; - request.telefon = "+420 123-456.789".into(); - request.ulica = "Náměstí 28. října".into(); - - let response = post_adresar(&pool, request.clone()).await.unwrap(); - assert_eq!(response.telefon, request.telefon); - assert_eq!(response.ulica, request.ulica); -} - -#[rstest] -#[tokio::test] -async fn test_create_adresar_optional_fields_null_vs_empty( - #[future] pool: PgPool, - valid_request: PostAdresarRequest, -) { - let pool = pool.await; - let mut request = valid_request; - request.telefon = String::new(); - let response = post_adresar(&pool, request).await.unwrap(); - - let db_telefon = sqlx::query_scalar!("SELECT telefon FROM adresar WHERE id = $1", response.id) - .fetch_one(&pool) - .await - .unwrap(); - - assert!(db_telefon.is_none()); -} diff --git a/server/tests/adresar/put_adresar_test.rs b/server/tests/adresar/put_adresar_test.rs deleted file mode 100644 index a974e6e..0000000 --- a/server/tests/adresar/put_adresar_test.rs +++ /dev/null @@ -1,266 +0,0 @@ -// tests/adresar/put_adresar_test.rs -use rstest::{fixture, rstest}; -use server::adresar::handlers::put_adresar; -use common::proto::multieko2::adresar::PutAdresarRequest; -use crate::common::setup_test_db; -use sqlx::PgPool; -use tonic; - -// Fixtures -#[fixture] -async fn pool() -> PgPool { - setup_test_db().await -} - -#[fixture] -async fn closed_pool(#[future] pool: PgPool) -> PgPool { - let pool = pool.await; - pool.close().await; - pool -} - -#[fixture] -async fn existing_record(#[future] pool: PgPool) -> (PgPool, i64) { - let pool = pool.await; - - // Create a test record in the database - let record = sqlx::query!( - r#" - INSERT INTO adresar ( - firma, kz, drc, ulica, psc, mesto, stat, banka, ucet, - skladm, ico, kontakt, telefon, skladu, fax, deleted - ) - VALUES ( - 'Original Company', 'Original KZ', 'Original DRC', 'Original Street', - '12345', 'Original City', 'Original Country', 'Original Bank', - 'Original Account', 'Original SkladM', 'Original ICO', - 'Original Contact', '+421123456789', 'Original SkladU', 'Original Fax', - false - ) - RETURNING id - "# - ) - .fetch_one(&pool) - .await - .unwrap(); - - (pool, record.id) -} - -#[fixture] -fn valid_request_template() -> PutAdresarRequest { - PutAdresarRequest { - id: 0, // This will be replaced in each test - firma: "Updated Company".into(), - kz: "Updated KZ".into(), - drc: "Updated DRC".into(), - ulica: "Updated Street".into(), - psc: "67890".into(), - mesto: "Updated City".into(), - stat: "Updated Country".into(), - banka: "Updated Bank".into(), - ucet: "987654321".into(), - skladm: "Updated SkladM".into(), - ico: "87654321".into(), - kontakt: "Jane Doe".into(), - telefon: "+421987654321".into(), - skladu: "Updated SkladU".into(), - fax: "+421987654300".into(), - } -} - -// Helper to check database state -async fn assert_response_matches(pool: &PgPool, id: i64, response: &common::proto::multieko2::adresar::AdresarResponse) { - let db_record = sqlx::query!("SELECT * FROM adresar WHERE id = $1", id) - .fetch_one(pool) - .await - .unwrap(); - - assert_eq!(db_record.firma, response.firma); - assert_eq!(db_record.kz.unwrap_or_default(), response.kz); - assert_eq!(db_record.drc.unwrap_or_default(), response.drc); - assert_eq!(db_record.ulica.unwrap_or_default(), response.ulica); - assert_eq!(db_record.psc.unwrap_or_default(), response.psc); - assert_eq!(db_record.mesto.unwrap_or_default(), response.mesto); - assert_eq!(db_record.stat.unwrap_or_default(), response.stat); - assert_eq!(db_record.banka.unwrap_or_default(), response.banka); - assert_eq!(db_record.ucet.unwrap_or_default(), response.ucet); - assert_eq!(db_record.skladm.unwrap_or_default(), response.skladm); - assert_eq!(db_record.ico.unwrap_or_default(), response.ico); - assert_eq!(db_record.kontakt.unwrap_or_default(), response.kontakt); - assert_eq!(db_record.telefon.unwrap_or_default(), response.telefon); - assert_eq!(db_record.skladu.unwrap_or_default(), response.skladu); - assert_eq!(db_record.fax.unwrap_or_default(), response.fax); - assert!(!db_record.deleted, "Record should not be deleted"); -} - -// Tests -#[rstest] -#[tokio::test] -async fn test_update_adresar_success(#[future] existing_record: (PgPool, i64), valid_request_template: PutAdresarRequest) { - let (pool, id) = existing_record.await; - - let mut request = valid_request_template; - request.id = id; - - let response = put_adresar(&pool, request).await.unwrap(); - - assert_eq!(response.id, id); - assert_response_matches(&pool, id, &response).await; -} - -#[rstest] -#[tokio::test] -async fn test_update_whitespace_fields(#[future] existing_record: (PgPool, i64), valid_request_template: PutAdresarRequest) { - let (pool, id) = existing_record.await; - - let mut request = valid_request_template; - request.id = id; - request.firma = " Updated Company ".into(); - request.telefon = " +421987654321 ".into(); - - let response = put_adresar(&pool, request).await.unwrap(); - - // Verify trimmed values in response - assert_eq!(response.firma, "Updated Company"); - assert_eq!(response.telefon, "+421987654321"); - - // Verify raw values in database - let db_record = sqlx::query!("SELECT firma, telefon FROM adresar WHERE id = $1", id) - .fetch_one(&pool) - .await - .unwrap(); - - assert_eq!(db_record.firma, "Updated Company"); // Trimmed - assert_eq!(db_record.telefon.unwrap(), "+421987654321"); // Trimmed -} - -#[rstest] -#[tokio::test] -async fn test_update_empty_required_field(#[future] existing_record: (PgPool, i64), valid_request_template: PutAdresarRequest) { - let (pool, id) = existing_record.await; - - let mut request = valid_request_template; - request.id = id; - request.firma = "".into(); - - let result = put_adresar(&pool, request).await; - assert!(result.is_err()); - assert_eq!(result.unwrap_err().code(), tonic::Code::InvalidArgument); -} - -#[rstest] -#[tokio::test] -async fn test_update_nonexistent_id(#[future] pool: PgPool) { - let pool = pool.await; - - let request = PutAdresarRequest { - id: 9999, // Non-existent ID - firma: "Updated Company".into(), - kz: "Updated KZ".into(), - drc: "Updated DRC".into(), - ulica: "Updated Street".into(), - psc: "67890".into(), - mesto: "Updated City".into(), - stat: "Updated Country".into(), - banka: "Updated Bank".into(), - ucet: "987654321".into(), - skladm: "Updated SkladM".into(), - ico: "87654321".into(), - kontakt: "Jane Doe".into(), - telefon: "+421987654321".into(), - skladu: "Updated SkladU".into(), - fax: "+421987654300".into(), - }; - - let result = put_adresar(&pool, request).await; - assert!(result.is_err()); - assert_eq!(result.unwrap_err().code(), tonic::Code::Internal); -} - -#[rstest] -#[tokio::test] -async fn test_update_deleted_record(#[future] existing_record: (PgPool, i64), valid_request_template: PutAdresarRequest) { - let (pool, id) = existing_record.await; - - // Mark the record as deleted - sqlx::query!("UPDATE adresar SET deleted = true WHERE id = $1", id) - .execute(&pool) - .await - .unwrap(); - - let mut request = valid_request_template; - request.id = id; - - let result = put_adresar(&pool, request).await; - assert!(result.is_err()); - assert_eq!(result.unwrap_err().code(), tonic::Code::Internal); -} - -#[rstest] -#[tokio::test] -async fn test_clear_optional_fields(#[future] existing_record: (PgPool, i64), valid_request_template: PutAdresarRequest) { - let (pool, id) = existing_record.await; - - let mut request = valid_request_template; - request.id = id; - request.telefon = String::new(); - request.ulica = String::new(); - - let response = put_adresar(&pool, request).await.unwrap(); - - // Check response contains empty strings - assert!(response.telefon.is_empty()); - assert!(response.ulica.is_empty()); - - // Check database contains NULL - let db_record = sqlx::query!("SELECT telefon, ulica FROM adresar WHERE id = $1", id) - .fetch_one(&pool) - .await - .unwrap(); - - assert!(db_record.telefon.is_none()); - assert!(db_record.ulica.is_none()); -} - -#[rstest] -#[tokio::test] -async fn test_max_length_fields(#[future] existing_record: (PgPool, i64), valid_request_template: PutAdresarRequest) { - let (pool, id) = existing_record.await; - - let mut request = valid_request_template; - request.id = id; - request.firma = "a".repeat(255); - request.telefon = "1".repeat(20); - - let _response = put_adresar(&pool, request).await.unwrap(); - - let db_record = sqlx::query!("SELECT firma, telefon FROM adresar WHERE id = $1", id) - .fetch_one(&pool) - .await - .unwrap(); - - assert_eq!(db_record.firma.len(), 255); - assert_eq!(db_record.telefon.unwrap().len(), 20); -} - -#[rstest] -#[tokio::test] -async fn test_special_characters(#[future] existing_record: (PgPool, i64), valid_request_template: PutAdresarRequest) { - let (pool, id) = existing_record.await; - - let mut request = valid_request_template; - request.id = id; - request.ulica = "Náměstí 28. října".into(); - request.telefon = "+420 123-456.789".into(); - - let _response = put_adresar(&pool, request).await.unwrap(); - - let db_record = sqlx::query!("SELECT ulica, telefon FROM adresar WHERE id = $1", id) - .fetch_one(&pool) - .await - .unwrap(); - - assert_eq!(db_record.ulica.unwrap(), "Náměstí 28. října"); - assert_eq!(db_record.telefon.unwrap(), "+420 123-456.789"); -} diff --git a/server/tests/mod.rs b/server/tests/mod.rs index a533032..09829a3 100644 --- a/server/tests/mod.rs +++ b/server/tests/mod.rs @@ -1,5 +1,4 @@ // tests/mod.rs -// pub mod adresar; pub mod tables_data; pub mod common; // pub mod table_definition;