diff --git a/server/tests/tables_data/handlers/get_table_data_count_test.rs b/server/tests/tables_data/handlers/get_table_data_count_test.rs new file mode 100644 index 0000000..e72a9f7 --- /dev/null +++ b/server/tests/tables_data/handlers/get_table_data_count_test.rs @@ -0,0 +1,202 @@ +// tests/tables_data/handlers/get_table_data_count_test.rs +use rstest::{fixture, rstest}; +use tonic; +use sqlx::PgPool; +use common::proto::multieko2::tables_data::GetTableDataCountRequest; +use server::tables_data::handlers::get_table_data_count; + +use crate::common::setup_test_db; + +#[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 +} + +#[rstest] +#[tokio::test] +async fn test_returns_correct_count(#[future] pool: PgPool) { + let pool = pool.await; + let mut tx = pool.begin().await.unwrap(); + + // Setup profile and table definition + let profile_id = sqlx::query_scalar!( + "INSERT INTO profiles (name) VALUES ('test_profile') RETURNING id" + ) + .fetch_one(&mut *tx) + .await + .unwrap(); + + sqlx::query!( + "INSERT INTO table_definitions (profile_id, table_name) VALUES ($1, 'adresar')", + profile_id + ) + .execute(&mut *tx) + .await + .unwrap(); + + // Insert test data + sqlx::query!("INSERT INTO adresar (firma, deleted) VALUES ('Test 1', FALSE)") + .execute(&mut *tx) + .await + .unwrap(); + sqlx::query!("INSERT INTO adresar (firma, deleted) VALUES ('Test 2', FALSE)") + .execute(&mut *tx) + .await + .unwrap(); + + // Commit to make data visible to handler + tx.commit().await.unwrap(); + + // Call handler + let request = GetTableDataCountRequest { + profile_name: "test_profile".to_string(), + table_name: "adresar".to_string(), + }; + let response = get_table_data_count(&pool, request).await.unwrap(); + + assert_eq!(response.count, 2); + + // Cleanup + let mut cleanup_tx = pool.begin().await.unwrap(); + sqlx::query!("DELETE FROM adresar WHERE firma LIKE 'Test%'") + .execute(&mut *cleanup_tx) + .await + .unwrap(); + cleanup_tx.commit().await.unwrap(); +} + +#[rstest] +#[tokio::test] +async fn test_excludes_deleted_records(#[future] pool: PgPool) { + let pool = pool.await; + let mut tx = pool.begin().await.unwrap(); + + let profile_id = sqlx::query_scalar!( + "INSERT INTO profiles (name) VALUES ('test_profile') RETURNING id" + ) + .fetch_one(&mut *tx) + .await + .unwrap(); + + sqlx::query!( + "INSERT INTO table_definitions (profile_id, table_name) VALUES ($1, 'adresar')", + profile_id + ) + .execute(&mut *tx) + .await + .unwrap(); + + // Insert active and deleted records + sqlx::query!("INSERT INTO adresar (firma, deleted) VALUES ('Active', FALSE)") + .execute(&mut *tx) + .await + .unwrap(); + sqlx::query!("INSERT INTO adresar (firma, deleted) VALUES ('Deleted', TRUE)") + .execute(&mut *tx) + .await + .unwrap(); + + tx.commit().await.unwrap(); + + let request = GetTableDataCountRequest { + profile_name: "test_profile".to_string(), + table_name: "adresar".to_string(), + }; + let response = get_table_data_count(&pool, request).await.unwrap(); + + assert_eq!(response.count, 1); +} + +#[rstest] +#[tokio::test] +async fn test_profile_not_found(#[future] pool: PgPool) { + let pool = pool.await; + + let request = GetTableDataCountRequest { + profile_name: "nonexistent_profile".to_string(), + table_name: "adresar".to_string(), + }; + let result = get_table_data_count(&pool, request).await; + + assert!(result.is_err()); + assert_eq!(result.unwrap_err().code(), tonic::Code::NotFound); +} + +#[rstest] +#[tokio::test] +async fn test_table_not_in_profile(#[future] pool: PgPool) { + let pool = pool.await; + let mut tx = pool.begin().await.unwrap(); + + let profile_id = sqlx::query_scalar!( + "INSERT INTO profiles (name) VALUES ('test_profile') RETURNING id" + ) + .fetch_one(&mut *tx) + .await + .unwrap(); + + // Do not link 'adresar' to profile + tx.commit().await.unwrap(); + + let request = GetTableDataCountRequest { + profile_name: "test_profile".to_string(), + table_name: "adresar".to_string(), + }; + let result = get_table_data_count(&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 = GetTableDataCountRequest { + profile_name: "test".to_string(), + table_name: "test".to_string(), + }; + let result = get_table_data_count(&closed_pool, request).await; + + assert!(result.is_err()); + assert_eq!(result.unwrap_err().code(), tonic::Code::Internal); +} + +#[rstest] +#[tokio::test] +async fn test_empty_table_count(#[future] pool: PgPool) { + let pool = pool.await; + let mut tx = pool.begin().await.unwrap(); + + let profile_id = sqlx::query_scalar!( + "INSERT INTO profiles (name) VALUES ('empty_test') RETURNING id" + ) + .fetch_one(&mut *tx) + .await + .unwrap(); + + sqlx::query!( + "INSERT INTO table_definitions (profile_id, table_name) VALUES ($1, 'adresar')", + profile_id + ) + .execute(&mut *tx) + .await + .unwrap(); + + tx.commit().await.unwrap(); + + let request = GetTableDataCountRequest { + profile_name: "empty_test".to_string(), + table_name: "adresar".to_string(), + }; + let response = get_table_data_count(&pool, request).await.unwrap(); + + assert!(response.count >= 0); +} diff --git a/server/tests/tables_data/handlers/mod.rs b/server/tests/tables_data/handlers/mod.rs index 189ddb4..f355db9 100644 --- a/server/tests/tables_data/handlers/mod.rs +++ b/server/tests/tables_data/handlers/mod.rs @@ -3,4 +3,5 @@ pub mod post_table_data_test; pub mod put_table_data_test; pub mod delete_table_data_test; pub mod get_table_data_test; +pub mod get_table_data_count_test;