From 512b061c7ada56a8691c621110c3837c9bf4d868 Mon Sep 17 00:00:00 2001 From: Max Hohlfeld Date: Tue, 1 Jul 2025 16:40:40 +0200 Subject: [PATCH] test: WIP new assignment --- .env.test | 1 + db/src/models/assignment_changeset.rs | 6 ++ db/src/models/user.rs | 2 +- web/src/endpoints/assignment/delete.rs | 2 +- web/src/endpoints/assignment/post_new.rs | 126 ++++++++++++++++++++-- web/src/endpoints/user/post_edit.rs | 9 +- web/src/endpoints/user/post_new.rs | 2 +- web/src/endpoints/user/put_lock.rs | 4 +- web/src/utils/test_helper/test_context.rs | 10 +- 9 files changed, 144 insertions(+), 18 deletions(-) diff --git a/.env.test b/.env.test index 94d6bf94..a3eda3fd 100644 --- a/.env.test +++ b/.env.test @@ -16,3 +16,4 @@ SMTP_PORT="1025" # SMTP_LOGIN="" # SMTP_PASSWORD="" SMTP_TLSTYPE="none" +RUST_LOG="info,brass_web=trace,brass_db=trace" diff --git a/db/src/models/assignment_changeset.rs b/db/src/models/assignment_changeset.rs index 37eaf071..ca2e7186 100644 --- a/db/src/models/assignment_changeset.rs +++ b/db/src/models/assignment_changeset.rs @@ -1,5 +1,6 @@ use chrono::NaiveDateTime; use sqlx::PgPool; +use tracing::debug; use crate::validation::{ AsyncValidate, AsyncValidateError, start_date_time_lies_before_end_date_time, @@ -116,6 +117,11 @@ async fn event_has_free_slot_for_function( .filter(|a| a.function == *value) .count(); + debug!( + assignments_with_function, + "existing assignments for function" + ); + if match *value { Function::Posten => assignments_with_function >= event.amount_of_posten as usize, Function::Fuehrungsassistent => { diff --git a/db/src/models/user.rs b/db/src/models/user.rs index 160278b6..97d069f4 100644 --- a/db/src/models/user.rs +++ b/db/src/models/user.rs @@ -20,7 +20,7 @@ pub struct User { } impl User { - pub async fn create(pool: &PgPool, changeset: UserChangeset) -> Result { + pub async fn create(pool: &PgPool, changeset: &UserChangeset) -> Result { sqlx::query!( r#" INSERT INTO user_ (name, email, role, function, areaId) diff --git a/web/src/endpoints/assignment/delete.rs b/web/src/endpoints/assignment/delete.rs index c0a606ea..88193eed 100644 --- a/web/src/endpoints/assignment/delete.rs +++ b/web/src/endpoints/assignment/delete.rs @@ -80,7 +80,7 @@ mod tests { async fn arrange(pool: &PgPool) -> anyhow::Result<()> { Location::create(pool, "Location", 1).await?; - User::create(pool, Faker.fake()).await?; + User::create(pool, &Faker.fake()).await?; let date: NaiveDate = Date().fake(); let start = NaiveTime::from_hms_opt(10, 0, 0).unwrap(); diff --git a/web/src/endpoints/assignment/post_new.rs b/web/src/endpoints/assignment/post_new.rs index 2ae1b4dc..c01a55d4 100644 --- a/web/src/endpoints/assignment/post_new.rs +++ b/web/src/endpoints/assignment/post_new.rs @@ -78,13 +78,14 @@ pub async fn post( mod tests { use actix_http::StatusCode; use brass_db::models::{ - Area, Availability, AvailabilityChangeset, Event, EventChangeset, Location, Role, User, - UserChangeset, + Area, Assignment, AssignmentChangeset, Availability, AvailabilityChangeset, Event, + EventChangeset, Function, Location, Role, User, UserChangeset, }; use brass_macros::db_test; use chrono::NaiveDateTime; use fake::{Fake, Faker}; use sqlx::PgPool; + use tracing::info; use crate::utils::test_helper::{ assert_snapshot, test_post, DbTestContext, NaiveDateTimeExt, RequestConfig, @@ -99,7 +100,7 @@ mod tests { let mut user_changeset: UserChangeset = Faker.fake(); user_changeset.name = String::from("Max Mustermann"); - User::create(pool, user_changeset).await.unwrap(); + User::create(pool, &user_changeset).await.unwrap(); } async fn arrange_event(pool: &PgPool, start: NaiveDateTime, end: NaiveDateTime, location: i32) { @@ -228,7 +229,23 @@ mod tests { #[db_test] fn fails_assignment_time_doesnt_fit_into_availability_time(context: &DbTestContext) { - assert!(false) + let app = context.app().await; + + let start = NaiveDateTime::from_ymd_and_hms(2025, 01, 10, 10, 0, 0).unwrap(); + let end = NaiveDateTime::from_ymd_and_hms(2025, 01, 10, 20, 0, 0).unwrap(); + let availability_start = NaiveDateTime::from_ymd_and_hms(2025, 01, 12, 10, 0, 0).unwrap(); + let availability_end = NaiveDateTime::from_ymd_and_hms(2025, 01, 10, 18, 0, 0).unwrap(); + + arrange(&context.db_pool).await; + arrange_event(&context.db_pool, start, end, 1).await; + arrange_availability(&context.db_pool, availability_start, availability_end).await; + + let config = RequestConfig::new("/assignments/new?availability=1&function=1&event=1") + .with_role(Role::Admin); + + let response = test_post::<_, _, String>(&context.db_pool, app, &config, None).await; + + assert_eq!(StatusCode::UNPROCESSABLE_ENTITY, response.status()); } #[db_test] @@ -238,16 +255,111 @@ mod tests { #[db_test] fn fails_when_availability_time_already_assigned(context: &DbTestContext) { - assert!(false) + let app = context.app().await; + + let start = NaiveDateTime::from_ymd_and_hms(2025, 01, 10, 10, 0, 0).unwrap(); + let end = NaiveDateTime::from_ymd_and_hms(2025, 01, 10, 20, 0, 0).unwrap(); + + arrange(&context.db_pool).await; + arrange_event(&context.db_pool, start, end, 1).await; + arrange_availability(&context.db_pool, start, end).await; + + let assignment_changeset = AssignmentChangeset { + function: Function::Posten, + time: (start, end), + }; + + Assignment::create(&context.db_pool, 1, 1, assignment_changeset) + .await + .unwrap(); + + let config = RequestConfig::new("/assignments/new?availability=1&function=1&event=1") + .with_role(Role::Admin); + + let response = test_post::<_, _, String>(&context.db_pool, app, &config, None).await; + + assert_eq!(StatusCode::UNPROCESSABLE_ENTITY, response.status()); } #[db_test] fn fails_when_availability_user_does_not_have_function(context: &DbTestContext) { - assert!(false) + let app = context.app().await; + + let start = NaiveDateTime::from_ymd_and_hms(2025, 01, 10, 10, 0, 0).unwrap(); + let end = NaiveDateTime::from_ymd_and_hms(2025, 01, 10, 20, 0, 0).unwrap(); + + arrange(&context.db_pool).await; + arrange_event(&context.db_pool, start, end, 1).await; + arrange_availability(&context.db_pool, start, end).await; + + let config = RequestConfig::new("/assignments/new?availability=1&function=5&event=1") + .with_role(Role::Admin); + + let response = test_post::<_, _, String>(&context.db_pool, app, &config, None).await; + + assert_eq!(StatusCode::UNPROCESSABLE_ENTITY, response.status()); } #[db_test] fn fails_when_event_already_has_enough_assignments_for_function(context: &DbTestContext) { - assert!(false) + let app = context.app().await; + info!("Hallo welt"); + + let start = NaiveDateTime::from_ymd_and_hms(2025, 01, 10, 10, 0, 0).unwrap(); + let end = NaiveDateTime::from_ymd_and_hms(2025, 01, 10, 20, 0, 0).unwrap(); + + Location::create(&context.db_pool, &Faker.fake::(), 1) + .await + .unwrap(); + + let mut user_changeset: UserChangeset = Faker.fake(); + user_changeset.functions.push(Function::Fuehrungsassistent); + + User::create(&context.db_pool, &user_changeset) + .await + .unwrap(); + User::create(&context.db_pool, &user_changeset) + .await + .unwrap(); + + arrange_event(&context.db_pool, start, end, 1).await; + + Availability::create( + &context.db_pool, + 1, + AvailabilityChangeset { + time: (start, end), + comment: None, + }, + ) + .await + .unwrap(); + + Availability::create( + &context.db_pool, + 2, + AvailabilityChangeset { + time: (start, end), + comment: None, + }, + ) + .await + .unwrap(); + + let assignment_changeset = AssignmentChangeset { + function: Function::Fuehrungsassistent, + time: (start, end), + }; + + Assignment::create(&context.db_pool, 1, 1, assignment_changeset) + .await + .unwrap(); + + let config = RequestConfig::new("/assignments/new?availability=2&function=5&event=1") + .with_role(Role::Admin); + + let response = test_post::<_, _, String>(&context.db_pool, app, &config, None).await; + + assert_eq!(StatusCode::UNPROCESSABLE_ENTITY, response.status()); } } diff --git a/web/src/endpoints/user/post_edit.rs b/web/src/endpoints/user/post_edit.rs index 898e16da..39b27cf1 100644 --- a/web/src/endpoints/user/post_edit.rs +++ b/web/src/endpoints/user/post_edit.rs @@ -91,7 +91,7 @@ mod tests { #[db_test] async fn works_when_user_is_admin(context: &DbTestContext) { - User::create(&context.db_pool, Faker.fake()).await.unwrap(); + User::create(&context.db_pool, &Faker.fake()).await.unwrap(); Area::create(&context.db_pool, "Süd").await.unwrap(); @@ -157,8 +157,7 @@ mod tests { #[db_test] async fn email_gets_cast_to_lowercase(context: &DbTestContext) { - User::create(&context.db_pool, Faker.fake()).await.unwrap(); - Area::create(&context.db_pool, "Süd").await.unwrap(); + User::create(&context.db_pool, &Faker.fake()).await.unwrap(); let app = context.app().await; let config = RequestConfig::new("/users/edit/1").with_role(Role::Admin); @@ -189,8 +188,8 @@ mod tests { #[db_test] async fn fails_when_email_already_present(context: &DbTestContext) { - User::create(&context.db_pool, Faker.fake()).await.unwrap(); - User::create(&context.db_pool, Faker.fake()).await.unwrap(); + User::create(&context.db_pool, &Faker.fake()).await.unwrap(); + User::create(&context.db_pool, &Faker.fake()).await.unwrap(); Area::create(&context.db_pool, "Süd").await.unwrap(); let app = context.app().await; diff --git a/web/src/endpoints/user/post_new.rs b/web/src/endpoints/user/post_new.rs index c17da900..b271f6d9 100644 --- a/web/src/endpoints/user/post_new.rs +++ b/web/src/endpoints/user/post_new.rs @@ -61,7 +61,7 @@ pub async fn post_new( return Ok(HttpResponse::UnprocessableEntity().body(e.to_string())); }; - let id = User::create(pool.get_ref(), changeset).await?; + let id = User::create(pool.get_ref(), &changeset).await?; let registration = Registration::insert_new_for_user(pool.get_ref(), id).await?; let new_user = User::read_by_id(pool.get_ref(), id).await?.unwrap(); diff --git a/web/src/endpoints/user/put_lock.rs b/web/src/endpoints/user/put_lock.rs index 3342ac0c..88096280 100644 --- a/web/src/endpoints/user/put_lock.rs +++ b/web/src/endpoints/user/put_lock.rs @@ -92,7 +92,7 @@ mod tests { #[db_test] async fn admin_can_lock_and_unlock_user(context: &DbTestContext) { let app = context.app().await; - User::create(&context.db_pool, Faker.fake()).await.unwrap(); + User::create(&context.db_pool, &Faker.fake()).await.unwrap(); let lock_config = RequestConfig { uri: "/users/1/lock".to_string(), @@ -127,7 +127,7 @@ mod tests { async fn area_manager_cant_lock_outside_of_his_area(context: &DbTestContext) { let app = context.app().await; Area::create(&context.db_pool, "Bereich 2").await.unwrap(); - User::create(&context.db_pool, Faker.fake()).await.unwrap(); + User::create(&context.db_pool, &Faker.fake()).await.unwrap(); let config = RequestConfig { uri: "/users/1/lock".to_string(), diff --git a/web/src/utils/test_helper/test_context.rs b/web/src/utils/test_helper/test_context.rs index 1cd1e97d..ad949d67 100644 --- a/web/src/utils/test_helper/test_context.rs +++ b/web/src/utils/test_helper/test_context.rs @@ -7,6 +7,7 @@ use actix_web::{ test::init_service, }; use rand::{distr::Alphanumeric, rng, Rng}; +use tracing_subscriber::{fmt, layer::SubscriberExt, registry, util::SubscriberInitExt, EnvFilter}; use crate::utils::Customization; use crate::{create_app, mail::Mailer}; @@ -32,7 +33,7 @@ impl DbTestContext { > { let customization = Customization { webmaster_email: self.config.webmaster_email.clone(), - hostname: self.config.hostname.clone() + hostname: self.config.hostname.clone(), }; init_service(create_app( @@ -50,6 +51,13 @@ pub async fn setup() -> DbTestContext { let init_config: OnceCell = OnceCell::new(); let config = init_config.get_or_init(|| load_config(&Environment::Test).unwrap()); + // TODO: unite with init_tracing in main + let filter = EnvFilter::try_from_default_env() + .or_else(|_| EnvFilter::try_new("info")) + .unwrap(); + + registry().with(fmt::layer()).with(filter).init(); + let test_db_config = prepare_db(&config.database_url).await; let test_db_pool = PgPoolOptions::new()