add tests for crew station size updates
Some checks failed
CI/CD Pipeline / test (push) Successful in 10m23s
CI/CD Pipeline / deploy (push) Has been cancelled

This commit is contained in:
2025-05-14 22:36:08 +02:00
parent f49af30c62
commit 97c176dbd5
7 changed files with 146 additions and 92 deletions

View File

@@ -31,12 +31,12 @@ impl Route {
.ok() .ok()
} }
async fn create(db: &SqlitePool, name: &str) -> Result<(), String> { pub(crate) async fn create(db: &SqlitePool, name: &str) -> Result<Self, String> {
sqlx::query!("INSERT INTO route(name) VALUES (?)", name) let route = sqlx::query!("INSERT INTO route(name) VALUES (?) RETURNING id", name)
.execute(db) .fetch_one(db)
.await .await
.map_err(|e| e.to_string())?; .map_err(|e| e.to_string())?;
Ok(()) Ok(Self::find_by_id(db, route.id).await.expect("just created"))
} }
async fn update_name(&self, db: &SqlitePool, name: &str) { async fn update_name(&self, db: &SqlitePool, name: &str) {

View File

@@ -72,7 +72,7 @@ async fn create(
Form(form): Form<CreateForm>, Form(form): Form<CreateForm>,
) -> impl IntoResponse { ) -> impl IntoResponse {
match Route::create(&db, &form.name).await { match Route::create(&db, &form.name).await {
Ok(()) => suc!(session, t!("route_create_succ", name = form.name)), Ok(_) => suc!(session, t!("route_create_succ", name = form.name)),
Err(e) => er!( Err(e) => er!(
session, session,
t!("route_create_err_duplicate_name", name = form.name, err = e) t!("route_create_err_duplicate_name", name = form.name, err = e)

View File

@@ -12,6 +12,7 @@ use serde::{Deserialize, Serialize};
use sqlx::{FromRow, Sqlite, SqlitePool, Transaction}; use sqlx::{FromRow, Sqlite, SqlitePool, Transaction};
use std::ops::DerefMut; use std::ops::DerefMut;
pub(crate) mod model;
pub(crate) mod print; pub(crate) mod print;
mod typst; mod typst;
mod web; mod web;
@@ -122,7 +123,7 @@ impl Station {
.unwrap(); .unwrap();
} }
pub(crate) async fn create(db: &SqlitePool, name: &str) -> Result<(), String> { pub(crate) async fn create(db: &SqlitePool, name: &str) -> Result<Self, String> {
let code = generate_random_alphanumeric(8); let code = generate_random_alphanumeric(8);
let station_id = sqlx::query!( let station_id = sqlx::query!(
"INSERT INTO station(name, pw) VALUES (?, ?) RETURNING id", "INSERT INTO station(name, pw) VALUES (?, ?) RETURNING id",
@@ -133,18 +134,18 @@ impl Station {
.await .await
.map_err(|e| e.to_string())?; .map_err(|e| e.to_string())?;
let mut routes = Route::all(db).await.into_iter();
if let Some(route) = routes.next() {
if routes.next().is_none() {
// Just one route exists -> use it for new station
let station = Station::find_by_id(db, station_id.id) let station = Station::find_by_id(db, station_id.id)
.await .await
.expect("just created"); .expect("just created");
let mut routes = Route::all(db).await.into_iter();
if let Some(route) = routes.next() {
if routes.next().is_none() {
// Just one route exists -> use it for new station
route.add_station(db, &station).await?; route.add_station(db, &station).await?;
} }
} }
Ok(()) Ok(station)
} }
pub(crate) async fn new_team_waiting( pub(crate) async fn new_team_waiting(
@@ -324,84 +325,6 @@ impl Station {
Ok(()) Ok(())
} }
async fn update_name(&self, db: &SqlitePool, name: &str) {
sqlx::query!("UPDATE station SET name = ? WHERE id = ?", name, self.id)
.execute(db)
.await
.unwrap();
}
async fn update_notes(&self, db: &SqlitePool, notes: &str) {
sqlx::query!("UPDATE station SET notes = ? WHERE id = ?", notes, self.id)
.execute(db)
.await
.unwrap();
}
async fn update_amount_people(
&self,
db: &SqlitePool,
amount_people: i64,
) -> Result<(), String> {
let mut transaction = db.begin().await.unwrap();
sqlx::query!(
"UPDATE station SET amount_people = ? WHERE id = ?",
amount_people,
self.id
)
.execute(transaction.deref_mut())
.await
.unwrap();
if amount_people == 0 {
let teams = self.teams(db).await;
for team in teams {
let route = team.route(db).await;
let Some(station) = route.get_next_first_station_tx(&mut transaction).await else {
return Err(t!("last_station_has_to_be_crewful").into());
};
team.update_first_station_tx(&mut transaction, &station)
.await;
}
}
transaction.commit().await.unwrap();
Ok(())
}
async fn update_amount_people_reset(&self, db: &SqlitePool) {
sqlx::query!(
"UPDATE station SET amount_people = NULL WHERE id = ?",
self.id
)
.execute(db)
.await
.unwrap();
}
async fn update_location(&self, db: &SqlitePool, lat: f64, lng: f64) {
sqlx::query!(
"UPDATE station SET lat = ?, lng = ? WHERE id = ?",
lat,
lng,
self.id
)
.execute(db)
.await
.unwrap();
}
async fn update_location_clear(&self, db: &SqlitePool) {
sqlx::query!(
"UPDATE station SET lat = NULL, lng=NULL WHERE id = ?",
self.id
)
.execute(db)
.await
.unwrap();
}
async fn delete(&self, db: &SqlitePool) -> Result<(), String> { async fn delete(&self, db: &SqlitePool) -> Result<(), String> {
sqlx::query!("DELETE FROM station WHERE id = ?", self.id) sqlx::query!("DELETE FROM station WHERE id = ?", self.id)
.execute(db) .execute(db)

View File

@@ -0,0 +1 @@
pub(crate) mod update;

View File

@@ -0,0 +1,125 @@
use crate::Station;
use sqlx::SqlitePool;
use std::ops::DerefMut;
impl Station {
pub(crate) async fn update_name(&self, db: &SqlitePool, name: &str) {
sqlx::query!("UPDATE station SET name = ? WHERE id = ?", name, self.id)
.execute(db)
.await
.unwrap();
}
pub(crate) async fn update_notes(&self, db: &SqlitePool, notes: &str) {
sqlx::query!("UPDATE station SET notes = ? WHERE id = ?", notes, self.id)
.execute(db)
.await
.unwrap();
}
pub(crate) async fn update_amount_people(
&self,
db: &SqlitePool,
amount_people: i64,
) -> Result<(), String> {
let mut transaction = db.begin().await.unwrap();
sqlx::query!(
"UPDATE station SET amount_people = ? WHERE id = ?",
amount_people,
self.id
)
.execute(transaction.deref_mut())
.await
.unwrap();
if amount_people == 0 {
let teams = self.teams(db).await;
for team in teams {
let route = team.route(db).await;
let Some(station) = route.get_next_first_station_tx(&mut transaction).await else {
return Err(t!("last_station_has_to_be_crewful").into());
};
team.update_first_station_tx(&mut transaction, &station)
.await;
}
}
transaction.commit().await.unwrap();
Ok(())
}
pub(crate) async fn update_amount_people_reset(&self, db: &SqlitePool) {
sqlx::query!(
"UPDATE station SET amount_people = NULL WHERE id = ?",
self.id
)
.execute(db)
.await
.unwrap();
}
pub(crate) async fn update_location(&self, db: &SqlitePool, lat: f64, lng: f64) {
sqlx::query!(
"UPDATE station SET lat = ?, lng = ? WHERE id = ?",
lat,
lng,
self.id
)
.execute(db)
.await
.unwrap();
}
pub(crate) async fn update_location_clear(&self, db: &SqlitePool) {
sqlx::query!(
"UPDATE station SET lat = NULL, lng=NULL WHERE id = ?",
self.id
)
.execute(db)
.await
.unwrap();
}
}
#[cfg(test)]
mod test {
use crate::{
admin::{route::Route, team::Team},
testdb, Station,
};
use sqlx::SqlitePool;
#[sqlx::test]
async fn succ_update_not_last_crewful_station() {
let pool = testdb!();
let station = Station::create(&pool, "Teststation").await.unwrap();
let crew_station = Station::create(&pool, "Bemannte Teststation")
.await
.unwrap();
let route = Route::create(&pool, "Testroute").await.unwrap();
route.add_station(&pool, &station).await.unwrap();
route.add_station(&pool, &crew_station).await.unwrap();
let _ = Team::create(&pool, "Testteam", &route).await.unwrap();
assert_eq!(station.update_amount_people(&pool, 0).await, Ok(()));
}
#[sqlx::test]
async fn fail_update_last_crewful_station() {
let pool = testdb!();
let station = Station::create(&pool, "Teststation").await.unwrap();
let route = Route::create(&pool, "Testroute").await.unwrap();
route.add_station(&pool, &station).await.unwrap();
let _ = Team::create(&pool, "Testteam", &route).await.unwrap();
assert_eq!(
station.update_amount_people(&pool, 0).await,
Err(t!("last_station_has_to_be_crewful").into())
);
}
}

View File

@@ -28,7 +28,7 @@ async fn create(
Form(form): Form<CreateForm>, Form(form): Form<CreateForm>,
) -> impl IntoResponse { ) -> impl IntoResponse {
match Station::create(&db, &form.name).await { match Station::create(&db, &form.name).await {
Ok(()) => suc!(session, t!("station_create_succ", name = form.name)), Ok(_) => suc!(session, t!("station_create_succ", name = form.name)),
Err(e) => er!( Err(e) => er!(
session, session,
t!( t!(

View File

@@ -88,7 +88,8 @@ ORDER BY
} }
} }
enum CreateError { #[derive(Debug)]
pub(crate) enum CreateError {
NoStationForRoute, NoStationForRoute,
DuplicateName(String), DuplicateName(String),
} }
@@ -147,7 +148,11 @@ impl Team {
.ok() .ok()
} }
async fn create(db: &SqlitePool, name: &str, route: &Route) -> Result<i64, CreateError> { pub(crate) async fn create(
db: &SqlitePool,
name: &str,
route: &Route,
) -> Result<i64, CreateError> {
// get next station id which has the lowest amount of teams to have in the first place // get next station id which has the lowest amount of teams to have in the first place
// assigned // assigned
let Some(station) = route.get_next_first_station(db).await else { let Some(station) = route.get_next_first_station(db).await else {