5 more tests to go

This commit is contained in:
filipriec
2025-06-21 21:01:49 +02:00
parent 298f56a53c
commit 06d98aab5c
5 changed files with 22 additions and 16 deletions

View File

@@ -8,6 +8,6 @@ reset_db:
run_tests: run_tests:
@echo "Running tests..." @echo "Running tests..."
@cargo test @cargo test --test mod -- --test-threads=1
.PHONY: test .PHONY: test

View File

@@ -229,7 +229,7 @@ async fn execute_table_definition(
return Err(Status::invalid_argument("Invalid column name")); return Err(Status::invalid_argument("Invalid column name"));
} }
if col_name.ends_with("_id") || col_name == "id" || col_name == "deleted" || col_name == "created_at" { if col_name.ends_with("_id") || col_name == "id" || col_name == "deleted" || col_name == "created_at" {
return Err(Status::invalid_argument("Invalid column name")); return Err(Status::invalid_argument("Column name cannot be 'id', 'deleted', 'created_at' or end with '_id'"));
} }
let sql_type = map_field_type(&col_def.field_type)?; let sql_type = map_field_type(&col_def.field_type)?;
columns.push(format!("\"{}\" {}", col_name, sql_type)); columns.push(format!("\"{}\" {}", col_name, sql_type));

View File

@@ -24,13 +24,17 @@ async fn get_root_connection() -> PgConnection {
/// This is the key to test isolation. /// This is the key to test isolation.
pub async fn setup_isolated_db() -> PgPool { pub async fn setup_isolated_db() -> PgPool {
let mut root_conn = get_root_connection().await; let mut root_conn = get_root_connection().await;
// Make schema names more unique - include timestamp + random
let schema_name = format!( let schema_name = format!(
"test_{}", "test_{}_{}",
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos(),
rand::thread_rng() rand::thread_rng()
// --- CHANGE 2: Pass a reference to Alphanumeric directly ---
.sample_iter(&Alphanumeric) .sample_iter(&Alphanumeric)
.take(12) .take(8)
.map(char::from) .map(char::from)
.collect::<String>() .collect::<String>()
.to_lowercase() .to_lowercase()

View File

@@ -157,8 +157,9 @@ async fn test_name_sanitization(#[future] pool: PgPool) {
#[tokio::test] #[tokio::test]
async fn test_create_minimal_table(#[future] pool: PgPool) { async fn test_create_minimal_table(#[future] pool: PgPool) {
let pool = pool.await; let pool = pool.await;
let profile_name = "test_minimal";
let req = PostTableDefinitionRequest { let req = PostTableDefinitionRequest {
profile_name: "default".into(), profile_name: profile_name.into(),
table_name: "minimal".into(), table_name: "minimal".into(),
..Default::default() ..Default::default()
}; };
@@ -168,7 +169,7 @@ async fn test_create_minimal_table(#[future] pool: PgPool) {
assert!(resp.sql.contains("created_at TIMESTAMPTZ")); assert!(resp.sql.contains("created_at TIMESTAMPTZ"));
assert_table_structure_is_correct( assert_table_structure_is_correct(
&pool, &pool,
"default", // FIXED: Added schema parameter profile_name,
"minimal", "minimal",
&[ &[
("id", "bigint"), ("id", "bigint"),

View File

@@ -162,26 +162,24 @@ async fn test_fail_gracefully_if_schema_is_missing(#[future] pool: PgPool) {
#[rstest] #[rstest]
#[tokio::test] #[tokio::test]
async fn test_column_name_with_id_suffix_is_rejected(#[future] pool: PgPool) { async fn test_column_name_with_id_suffix_is_rejected(#[future] pool: PgPool) {
// Test that column names ending with '_id' are properly rejected during input validation
let pool = pool.await; let pool = pool.await;
// Test 1: Column ending with '_id' should be rejected // Test 1: Column ending with '_id' should be rejected
let request = PostTableDefinitionRequest { let request = PostTableDefinitionRequest {
profile_name: "default".into(), profile_name: "default".into(),
table_name: "orders".into(), // Valid table name table_name: "orders".into(),
columns: vec![ColumnDefinition { columns: vec![ColumnDefinition {
name: "legacy_order_id".into(), // This should be rejected name: "legacy_order_id".into(),
field_type: "integer".into(), field_type: "integer".into(),
}], }],
..Default::default() ..Default::default()
}; };
// Act & Assert - should fail validation
let result = post_table_definition(&pool, request).await; let result = post_table_definition(&pool, request).await;
assert!(result.is_err(), "Column names ending with '_id' should be rejected"); assert!(result.is_err(), "Column names ending with '_id' should be rejected");
if let Err(status) = result { if let Err(status) = result {
assert_eq!(status.code(), tonic::Code::InvalidArgument); assert_eq!(status.code(), tonic::Code::InvalidArgument);
assert!(status.message().contains("Invalid column name")); // Update this line to match the actual error message:
assert!(status.message().contains("Column name cannot be") && status.message().contains("end with '_id'"));
} }
// Test 2: Column named exactly 'id' should be rejected // Test 2: Column named exactly 'id' should be rejected
@@ -189,14 +187,17 @@ async fn test_column_name_with_id_suffix_is_rejected(#[future] pool: PgPool) {
profile_name: "default".into(), profile_name: "default".into(),
table_name: "orders".into(), table_name: "orders".into(),
columns: vec![ColumnDefinition { columns: vec![ColumnDefinition {
name: "id".into(), // This should be rejected name: "id".into(),
field_type: "integer".into(), field_type: "integer".into(),
}], }],
..Default::default() ..Default::default()
}; };
let result2 = post_table_definition(&pool, request2).await; let result2 = post_table_definition(&pool, request2).await;
assert!(result2.is_err(), "Column named 'id' should be rejected"); assert!(result2.is_err(), "Column named 'id' should be rejected");
if let Err(status) = result2 {
assert_eq!(status.code(), tonic::Code::InvalidArgument);
assert!(status.message().contains("Column name cannot be") && status.message().contains("'id'"));
}
} }
#[rstest] #[rstest]