From da89715be3b17acaae7c452803cb9cb3338c4e0b Mon Sep 17 00:00:00 2001 From: filipriec Date: Mon, 24 Feb 2025 16:05:32 +0100 Subject: [PATCH] not working, rstest port --- Cargo.lock | 85 +++++++ server/Cargo.toml | 1 + server/tests/adresar/post_adresar_test.rs | 283 ++++++++++++---------- 3 files changed, 243 insertions(+), 126 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2b6f9c7..244cef0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -669,6 +669,17 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "futures-sink" version = "0.3.31" @@ -681,6 +692,12 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + [[package]] name = "futures-util" version = "0.3.31" @@ -689,6 +706,7 @@ checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-core", "futures-io", + "futures-macro", "futures-sink", "futures-task", "memchr", @@ -736,6 +754,12 @@ version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +[[package]] +name = "glob" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" + [[package]] name = "h2" version = "0.4.8" @@ -1572,6 +1596,15 @@ dependencies = [ "syn", ] +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit", +] + [[package]] name = "proc-macro2" version = "1.0.93" @@ -1742,6 +1775,12 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "relative-path" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" + [[package]] name = "rsa" version = "0.9.7" @@ -1762,12 +1801,51 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rstest" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03e905296805ab93e13c1ec3a03f4b6c4f35e9498a3d5fa96dc626d22c03cd89" +dependencies = [ + "futures-timer", + "futures-util", + "rstest_macros", + "rustc_version", +] + +[[package]] +name = "rstest_macros" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef0053bbffce09062bee4bcc499b0fbe7a57b879f1efe088d6d8d4c7adcdef9b" +dependencies = [ + "cfg-if", + "glob", + "proc-macro-crate", + "proc-macro2", + "quote", + "regex", + "relative-path", + "rustc_version", + "syn", + "unicode-ident", +] + [[package]] name = "rustc-demangle" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "0.38.44" @@ -1831,6 +1909,12 @@ dependencies = [ "libc", ] +[[package]] +name = "semver" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" + [[package]] name = "serde" version = "1.0.218" @@ -1893,6 +1977,7 @@ dependencies = [ "dotenv", "dotenvy", "prost", + "rstest", "serde", "serde_json", "sqlx", diff --git a/server/Cargo.toml b/server/Cargo.toml index 4914391..e6f4f97 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -25,3 +25,4 @@ path = "src/lib.rs" [dev-dependencies] tokio = { version = "1.0", features = ["full", "test-util"] } dotenv = "0.15" +rstest = "0.24.0" diff --git a/server/tests/adresar/post_adresar_test.rs b/server/tests/adresar/post_adresar_test.rs index 32439cc..8762d59 100644 --- a/server/tests/adresar/post_adresar_test.rs +++ b/server/tests/adresar/post_adresar_test.rs @@ -1,207 +1,238 @@ // tests/adresar/post_adresar_test.rs + +// Import the rstest attribute macros. +use rstest::{awt, 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; -// Helper functions -mod test_helpers { - use super::*; +// --- Fixtures --- - pub 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] +async fn pool() -> PgPool { + setup_test_db().await +} - pub fn minimal_request() -> PostAdresarRequest { - PostAdresarRequest { - firma: "Required Only".into(), - ..Default::default() - } - } +#[fixture] +async fn closed_pool(pool: PgPool) -> PgPool { + // Close the pool so we can simulate a DB error. + pool.close().await; + pool +} - pub async fn assert_response_matches(pool: &PgPool, response: &common::proto::multieko2::adresar::AdresarResponse) { - // Verify database state - 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, Some(response.telefon.clone())); - // Add assertions for other fields... - - // Verify default values - assert!(!db_record.deleted); - assert!(db_record.created_at.is_some()); +#[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() + } +} + +// A helper that checks that the database record matches the response. +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()) + ); + // More field comparisons can be added here… + + assert!(!db_record.deleted); + assert!(db_record.created_at.is_some()); +} + +// --- Tests --- + +#[rstest] +#[awt] // awaits all async fixture inputs #[tokio::test] -async fn test_create_adresar_success() { - let pool = setup_test_db().await; - let request = test_helpers::valid_request(); +async fn test_create_adresar_success(pool: PgPool, valid_request: PostAdresarRequest) { + let response = post_adresar(&pool, valid_request).await.unwrap(); - let response = post_adresar(&pool, request).await.unwrap(); - - // Basic response validation assert!(response.id > 0, "Should return positive ID"); assert_eq!(response.firma, "Test Company", "Firma should match"); - // Verify all fields against request - let request = test_helpers::valid_request(); - assert_eq!(response.kz, request.kz); - assert_eq!(response.drc, request.drc); - // Continue for all fields... - - // Comprehensive database check - test_helpers::assert_response_matches(&pool, &response).await; + // Comprehensive database check. + assert_response_matches(&pool, &response).await; } +#[rstest] +#[awt] #[tokio::test] -async fn test_create_adresar_whitespace_trimming() { - let pool = setup_test_db().await; +async fn test_create_adresar_whitespace_trimming( + pool: PgPool, + mut valid_request: PostAdresarRequest, +) { + // Change some fields to include extra whitespace. + valid_request.firma = " Test Company ".into(); + valid_request.telefon = " +421123456789 ".into(); + valid_request.ulica = " Test Street ".into(); - let mut request = test_helpers::valid_request(); - request.firma = " Test Company ".into(); - request.telefon = " +421123456789 ".into(); - request.ulica = " Test Street ".into(); - - let response = post_adresar(&pool, request).await.unwrap(); + let response = post_adresar(&pool, valid_request).await.unwrap(); assert_eq!(response.firma, "Test Company"); assert_eq!(response.telefon, "+421123456789"); assert_eq!(response.ulica, "Test Street"); } +#[rstest] +#[awt] #[tokio::test] -async fn test_create_adresar_empty_optional_fields() { - let pool = setup_test_db().await; +async fn test_create_adresar_empty_optional_fields( + pool: PgPool, + mut valid_request: PostAdresarRequest, +) { + valid_request.telefon = " ".into(); - let mut request = test_helpers::valid_request(); - request.telefon = " ".into(); // Only whitespace + let response = post_adresar(&pool, valid_request).await.unwrap(); - let response = post_adresar(&pool, request).await.unwrap(); - - // Should be stored as NULL in database - let record = sqlx::query!("SELECT telefon FROM adresar WHERE id = $1", response.id) + // Check in the database that telefono was stored as NULL. + let db_telefon = sqlx::query_scalar!("SELECT telefon FROM adresar WHERE id = $1", response.id) .fetch_one(&pool) .await .unwrap(); - assert!(record.telefon.is_none()); - assert_eq!(response.telefon, ""); // Still returns empty string + assert!(db_telefon.is_none()); + // The response still returns an empty string. + assert_eq!(response.telefon, ""); } +#[rstest] +#[awt] #[tokio::test] -async fn test_create_adresar_invalid_firma() { - let pool = setup_test_db().await; +async fn test_create_adresar_invalid_firma( + pool: PgPool, + mut valid_request: PostAdresarRequest, +) { + valid_request.firma = " ".into(); - let mut request = test_helpers::valid_request(); - request.firma = " ".into(); // Only whitespace - - let result = post_adresar(&pool, request).await; + let result = post_adresar(&pool, valid_request).await; assert!(result.is_err()); assert_eq!(result.unwrap_err().code(), tonic::Code::InvalidArgument); } +#[rstest] +#[awt] #[tokio::test] -async fn test_create_adresar_minimal_valid_request() { - let pool = setup_test_db().await; - let request = test_helpers::minimal_request(); - - let response = post_adresar(&pool, request).await.unwrap(); +async fn test_create_adresar_minimal_valid_request( + pool: PgPool, + minimal_request: PostAdresarRequest, +) { + let response = post_adresar(&pool, minimal_request).await.unwrap(); assert!(response.id > 0); assert_eq!(response.firma, "Required Only"); - // Verify optional fields are empty + // Verify that all other optional fields appear empty. assert!(response.kz.is_empty()); assert!(response.drc.is_empty()); - // Continue for all optional fields... + // ...and so on. } +#[rstest] +#[awt] #[tokio::test] -async fn test_create_adresar_empty_firma() { - let pool = setup_test_db().await; - let mut request = test_helpers::minimal_request(); - request.firma = "".into(); - - let result = post_adresar(&pool, request).await; +async fn test_create_adresar_empty_firma( + pool: PgPool, + mut minimal_request: PostAdresarRequest, +) { + minimal_request.firma = "".into(); + let result = post_adresar(&pool, minimal_request).await; assert!(result.is_err()); assert_eq!(result.unwrap_err().code(), tonic::Code::InvalidArgument); } +#[rstest] +#[awt] #[tokio::test] -async fn test_create_adresar_database_error() { - let pool = setup_test_db().await; - pool.close().await; - - let result = post_adresar(&pool, test_helpers::minimal_request()).await; - +async fn test_create_adresar_database_error( + closed_pool: PgPool, + minimal_request: PostAdresarRequest, +) { + let result = post_adresar(&closed_pool, minimal_request).await; assert!(result.is_err()); assert_eq!(result.unwrap_err().code(), tonic::Code::Internal); } +#[rstest] +#[awt] #[tokio::test] -async fn test_create_adresar_field_length_limits() { - let pool = setup_test_db().await; +async fn test_create_adresar_field_length_limits( + pool: PgPool, + mut valid_request: PostAdresarRequest, +) { + valid_request.firma = "a".repeat(255); + valid_request.telefon = "1".repeat(20); - let mut request = test_helpers::valid_request(); - request.firma = "a".repeat(255); - request.telefon = "1".repeat(20); // Example length based on DB schema - - let response = post_adresar(&pool, request).await.unwrap(); + let response = post_adresar(&pool, valid_request).await.unwrap(); assert_eq!(response.firma.len(), 255); assert_eq!(response.telefon.len(), 20); } +#[rstest] +#[awt] #[tokio::test] -async fn test_create_adresar_special_characters() { - let pool = setup_test_db().await; +async fn test_create_adresar_special_characters( + pool: PgPool, + mut valid_request: PostAdresarRequest, +) { + valid_request.telefon = "+420 123-456.789".into(); + valid_request.ulica = "Náměstí 28. října".into(); - let mut request = test_helpers::valid_request(); - request.telefon = "+420 123-456.789".into(); - request.ulica = "Náměstí 28. října".into(); + let response = post_adresar(&pool, valid_request.clone()).await.unwrap(); - let response = post_adresar(&pool, request.clone()).await.unwrap(); - - assert_eq!(response.telefon, request.telefon); - assert_eq!(response.ulica, request.ulica); + assert_eq!(response.telefon, valid_request.telefon); + assert_eq!(response.ulica, valid_request.ulica); } +#[rstest] +#[awt] #[tokio::test] -async fn test_create_adresar_optional_fields_null_vs_empty() { - let pool = setup_test_db().await; +async fn test_create_adresar_optional_fields_null_vs_empty( + pool: PgPool, + mut valid_request: PostAdresarRequest, +) { + valid_request.telefon = String::new(); - // Test explicit null (using default values) - let mut request = test_helpers::valid_request(); - request.telefon = String::new(); - - let response = post_adresar(&pool, request).await.unwrap(); - - // Verify empty string is stored as NULL in database - let record = sqlx::query!("SELECT telefon FROM adresar WHERE id = $1", response.id) + let response = post_adresar(&pool, valid_request).await.unwrap(); + let db_telefon = sqlx::query_scalar!("SELECT telefon FROM adresar WHERE id = $1", response.id) .fetch_one(&pool) .await .unwrap(); - assert!(record.telefon.is_none()); + assert!(db_telefon.is_none()); } +