test: new availability
This commit is contained in:
parent
760897b301
commit
98e42e20c8
@ -1,4 +1,4 @@
|
|||||||
use chrono::{Days, NaiveDateTime};
|
use chrono::{Days, NaiveDate, NaiveDateTime};
|
||||||
use sqlx::PgPool;
|
use sqlx::PgPool;
|
||||||
|
|
||||||
use super::Availability;
|
use super::Availability;
|
||||||
@ -150,3 +150,20 @@ pub fn find_free_date_time_slots(
|
|||||||
|
|
||||||
available_slots
|
available_slots
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "test-helpers")]
|
||||||
|
impl AvailabilityChangeset {
|
||||||
|
pub fn create_for_test(
|
||||||
|
date: &NaiveDate,
|
||||||
|
start_hour: u32,
|
||||||
|
end_hour: u32,
|
||||||
|
) -> AvailabilityChangeset {
|
||||||
|
AvailabilityChangeset {
|
||||||
|
time: (
|
||||||
|
date.and_hms_opt(start_hour, 0, 0).unwrap(),
|
||||||
|
date.and_hms_opt(end_hour, 0, 0).unwrap(),
|
||||||
|
),
|
||||||
|
comment: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -35,6 +35,7 @@ struct NewOrEditAvailabilityTemplate<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
#[cfg_attr(test, derive(serde::Serialize))]
|
||||||
pub struct AvailabilityForm {
|
pub struct AvailabilityForm {
|
||||||
pub startdate: NaiveDate,
|
pub startdate: NaiveDate,
|
||||||
pub enddate: NaiveDate,
|
pub enddate: NaiveDate,
|
||||||
|
@ -7,7 +7,7 @@ use crate::{
|
|||||||
utils::{self, ApplicationError},
|
utils::{self, ApplicationError},
|
||||||
};
|
};
|
||||||
use brass_db::{
|
use brass_db::{
|
||||||
models::{Availability, AvailabilityChangeset, AvailabilityContext, User},
|
models::{Availability, AvailabilityChangeset, AvailabilityContext, Role, User},
|
||||||
validation::AsyncValidate,
|
validation::AsyncValidate,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -20,6 +20,13 @@ pub async fn post(
|
|||||||
let start = form.startdate.and_time(form.starttime);
|
let start = form.startdate.and_time(form.starttime);
|
||||||
let end = form.enddate.and_time(form.endtime);
|
let end = form.enddate.and_time(form.endtime);
|
||||||
let user_for_availability = form.user.unwrap_or(user.id);
|
let user_for_availability = form.user.unwrap_or(user.id);
|
||||||
|
let Some(other_user) = User::read_by_id(pool.get_ref(), user_for_availability).await? else {
|
||||||
|
return Ok(HttpResponse::UnprocessableEntity().body("Nutzer existiert nicht."));
|
||||||
|
};
|
||||||
|
|
||||||
|
if other_user.area_id != user.area_id && user.role != Role::Admin {
|
||||||
|
return Err(ApplicationError::Unauthorized);
|
||||||
|
}
|
||||||
|
|
||||||
let context = AvailabilityContext {
|
let context = AvailabilityContext {
|
||||||
pool: pool.get_ref(),
|
pool: pool.get_ref(),
|
||||||
@ -75,3 +82,192 @@ pub async fn post(
|
|||||||
.insert_header(("HX-LOCATION", url))
|
.insert_header(("HX-LOCATION", url))
|
||||||
.finish())
|
.finish())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use actix_http::StatusCode;
|
||||||
|
use brass_db::models::{Area, Availability, AvailabilityChangeset, Role, User, UserChangeset};
|
||||||
|
use brass_macros::db_test;
|
||||||
|
use chrono::{NaiveDate, NaiveTime};
|
||||||
|
use fake::{Fake, Faker};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
endpoints::availability::AvailabilityForm,
|
||||||
|
utils::test_helper::{create_test_login_user, test_post, DbTestContext, RequestConfig},
|
||||||
|
};
|
||||||
|
|
||||||
|
fn create_form(
|
||||||
|
date: &NaiveDate,
|
||||||
|
start_hour: u32,
|
||||||
|
end_hour: u32,
|
||||||
|
user: Option<i32>,
|
||||||
|
) -> AvailabilityForm {
|
||||||
|
AvailabilityForm {
|
||||||
|
startdate: *date,
|
||||||
|
enddate: *date,
|
||||||
|
starttime: NaiveTime::from_hms_opt(start_hour, 0, 0).unwrap(),
|
||||||
|
endtime: NaiveTime::from_hms_opt(end_hour, 0, 0).unwrap(),
|
||||||
|
comment: None,
|
||||||
|
user,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[db_test]
|
||||||
|
async fn can_create_availability_for_myself_fine(context: &DbTestContext) {
|
||||||
|
let app = context.app().await;
|
||||||
|
|
||||||
|
let config = RequestConfig::new("/availability/new");
|
||||||
|
create_test_login_user(&context.db_pool, &config).await;
|
||||||
|
|
||||||
|
let date = Faker.fake();
|
||||||
|
let form = create_form(&date, 10, 20, None);
|
||||||
|
let response = test_post(app, &config, Some(form)).await;
|
||||||
|
|
||||||
|
assert_eq!(StatusCode::FOUND, response.status());
|
||||||
|
assert!(Availability::read(&context.db_pool, 1)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.is_some())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[db_test]
|
||||||
|
async fn cant_create_availability_for_myself_when_time_slot_already_present(
|
||||||
|
context: &DbTestContext,
|
||||||
|
) {
|
||||||
|
let app = context.app().await;
|
||||||
|
|
||||||
|
let config = RequestConfig::new("/availability/new");
|
||||||
|
create_test_login_user(&context.db_pool, &config).await;
|
||||||
|
|
||||||
|
let date = Faker.fake();
|
||||||
|
let changeset = AvailabilityChangeset::create_for_test(&date, 10, 20);
|
||||||
|
Availability::create(&context.db_pool, 1, &changeset)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let form = create_form(&date, 10, 20, None);
|
||||||
|
let response = test_post(app, &config, Some(form)).await;
|
||||||
|
|
||||||
|
assert_eq!(StatusCode::UNPROCESSABLE_ENTITY, response.status());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[db_test]
|
||||||
|
async fn create_new_updates_existing_when_time_slots_connect(context: &DbTestContext) {
|
||||||
|
let app = context.app().await;
|
||||||
|
|
||||||
|
let config = RequestConfig::new("/availability/new");
|
||||||
|
create_test_login_user(&context.db_pool, &config).await;
|
||||||
|
|
||||||
|
let date = Faker.fake();
|
||||||
|
let changeset = AvailabilityChangeset::create_for_test(&date, 4, 10);
|
||||||
|
Availability::create(&context.db_pool, 1, &changeset)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let form = create_form(&date, 10, 20, None);
|
||||||
|
let response = test_post(app, &config, Some(form)).await;
|
||||||
|
|
||||||
|
assert_eq!(StatusCode::FOUND, response.status());
|
||||||
|
assert_eq!(
|
||||||
|
1,
|
||||||
|
Availability::read_all_by_user_and_date(&context.db_pool, 1, &date)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.len()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[db_test]
|
||||||
|
async fn cant_create_availability_for_myself_when_start_time_before_end_time(
|
||||||
|
context: &DbTestContext,
|
||||||
|
) {
|
||||||
|
let app = context.app().await;
|
||||||
|
|
||||||
|
let config = RequestConfig::new("/availability/new");
|
||||||
|
create_test_login_user(&context.db_pool, &config).await;
|
||||||
|
|
||||||
|
let date = Faker.fake();
|
||||||
|
let form = create_form(&date, 20, 10, None);
|
||||||
|
let response = test_post(app, &config, Some(form)).await;
|
||||||
|
|
||||||
|
assert_eq!(StatusCode::UNPROCESSABLE_ENTITY, response.status());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[db_test]
|
||||||
|
async fn can_create_availability_for_other_user_in_same_area_as_area_manager(
|
||||||
|
context: &DbTestContext,
|
||||||
|
) {
|
||||||
|
let app = context.app().await;
|
||||||
|
|
||||||
|
let config = RequestConfig::new("/availability/new").with_role(Role::AreaManager);
|
||||||
|
create_test_login_user(&context.db_pool, &config).await;
|
||||||
|
|
||||||
|
User::create(&context.db_pool, &Faker.fake()).await.unwrap();
|
||||||
|
|
||||||
|
let date = Faker.fake();
|
||||||
|
let form = create_form(&date, 10, 20, Some(2));
|
||||||
|
let response = test_post(app, &config, Some(form)).await;
|
||||||
|
|
||||||
|
assert_eq!(StatusCode::FOUND, response.status());
|
||||||
|
assert_eq!(
|
||||||
|
1,
|
||||||
|
Availability::read_all_by_user_and_date(&context.db_pool, 2, &date)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.len()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[db_test]
|
||||||
|
async fn cant_create_availability_for_other_user_in_other_area_as_area_manager(
|
||||||
|
context: &DbTestContext,
|
||||||
|
) {
|
||||||
|
let app = context.app().await;
|
||||||
|
|
||||||
|
let config = RequestConfig::new("/availability/new").with_role(Role::AreaManager);
|
||||||
|
create_test_login_user(&context.db_pool, &config).await;
|
||||||
|
|
||||||
|
Area::create(&context.db_pool, "Süd").await.unwrap();
|
||||||
|
let mut user_changeset: UserChangeset = Faker.fake();
|
||||||
|
user_changeset.area_id = 2;
|
||||||
|
User::create(&context.db_pool, &user_changeset)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let date = Faker.fake();
|
||||||
|
let form = create_form(&date, 10, 20, Some(2));
|
||||||
|
let response = test_post(app, &config, Some(form)).await;
|
||||||
|
|
||||||
|
assert_eq!(StatusCode::UNAUTHORIZED, response.status());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[db_test]
|
||||||
|
async fn can_create_availability_for_other_user_in_other_area_as_admin(
|
||||||
|
context: &DbTestContext,
|
||||||
|
) {
|
||||||
|
let app = context.app().await;
|
||||||
|
|
||||||
|
let config = RequestConfig::new("/availability/new").with_role(Role::Admin);
|
||||||
|
create_test_login_user(&context.db_pool, &config).await;
|
||||||
|
|
||||||
|
Area::create(&context.db_pool, "Süd").await.unwrap();
|
||||||
|
let mut user_changeset: UserChangeset = Faker.fake();
|
||||||
|
user_changeset.area_id = 2;
|
||||||
|
User::create(&context.db_pool, &user_changeset)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let date = Faker.fake();
|
||||||
|
let form = create_form(&date, 10, 20, Some(2));
|
||||||
|
let response = test_post(app, &config, Some(form)).await;
|
||||||
|
|
||||||
|
assert_eq!(StatusCode::FOUND, response.status());
|
||||||
|
assert_eq!(
|
||||||
|
1,
|
||||||
|
Availability::read_all_by_user_and_date(&context.db_pool, 2, &date)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.len()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user