diff --git a/src/model/boat.rs b/src/model/boat.rs index 8ec7ff2..444dcbf 100644 --- a/src/model/boat.rs +++ b/src/model/boat.rs @@ -125,7 +125,7 @@ ORDER BY amount_seats DESC res } - pub async fn create(db: &SqlitePool, boat: BoatToAdd<'_>) -> bool { + pub async fn create(db: &SqlitePool, boat: BoatToAdd<'_>) -> Result<(), String> { sqlx::query!( "INSERT INTO boat(name, amount_seats, year_built, boatbuilder, default_shipmaster_only_steering, skull, external, location_id, owner) VALUES (?,?,?,?,?,?,?,?,?)", boat.name, @@ -139,7 +139,8 @@ ORDER BY amount_seats DESC boat.owner ) .execute(db) - .await.is_ok() + .await.map_err(|e| e.to_string())?; + Ok(()) } pub async fn update(&self, db: &SqlitePool, boat: BoatToUpdate<'_>) -> Result<(), String> { @@ -221,7 +222,7 @@ mod test { } ) .await, - true + Ok(()) ); } @@ -245,7 +246,10 @@ mod test { } ) .await, - false + Err( + "error returned from database: (code: 2067) UNIQUE constraint failed: boat.name" + .into() + ) ); } diff --git a/src/model/logtype.rs b/src/model/logtype.rs index 111d42d..03d1b05 100644 --- a/src/model/logtype.rs +++ b/src/model/logtype.rs @@ -2,12 +2,12 @@ use serde::{Deserialize, Serialize}; use sqlx::{FromRow, SqlitePool}; #[derive(FromRow, Debug, Serialize, Deserialize, Clone)] -pub struct LogType{ +pub struct LogType { pub id: i64, name: String, } -impl LogType{ +impl LogType { pub async fn find_by_id(db: &SqlitePool, id: i64) -> Option { sqlx::query_as!( Self, @@ -45,7 +45,7 @@ mod test { #[sqlx::test] fn test_find_true() { - let pool = testdb!(); + let _ = testdb!(); } //TODO: write tests diff --git a/src/tera/admin/boat.rs b/src/tera/admin/boat.rs index ac728fa..447f28f 100644 --- a/src/tera/admin/boat.rs +++ b/src/tera/admin/boat.rs @@ -74,16 +74,237 @@ async fn create( data: Form>, _admin: AdminUser, ) -> Flash { - if Boat::create(db, data.into_inner()).await { - Flash::success(Redirect::to("/admin/boat"), "Successfully created boat") - } else { - Flash::error( - Redirect::to("/admin/boat"), - "Error while creating the boat in DB", - ) + match Boat::create(db, data.into_inner()).await { + Ok(_) => Flash::success(Redirect::to("/admin/boat"), "Successfully created boat"), + Err(e) => Flash::error(Redirect::to("/admin/boat"), e), } } pub fn routes() -> Vec { routes![index, create, delete, update] } + +#[cfg(test)] +mod test { + use chrono::NaiveDate; + use rocket::{ + http::{ContentType, Status}, + local::asynchronous::Client, + }; + use sqlx::SqlitePool; + + use crate::tera::admin::boat::Boat; + use crate::{model::trip::Trip, testdb}; + + #[sqlx::test] + fn test_boat_index() { + let db = testdb!(); + + let rocket = rocket::build().manage(db.clone()); + let rocket = crate::tera::config(rocket); + + let client = Client::tracked(rocket).await.unwrap(); + let login = client + .post("/auth") + .header(ContentType::Form) // Set the content type to form + .body("name=admin&password=admin"); // Add the form data to the request body; + login.dispatch().await; + + let req = client.get("/admin/boat"); + let response = req.dispatch().await; + + assert_eq!(response.status(), Status::Ok); + let text = response.into_string().await.unwrap(); + assert!(&text.contains("Neues Boot hinzufügen")); + assert!(&text.contains("Kaputtes Boot :-(")); + assert!(&text.contains("Haichenbach")); + } + + #[sqlx::test] + fn test_succ_update() { + let db = testdb!(); + + let boat = Boat::find_by_id(&db, 1).await.unwrap(); + assert_eq!(boat.name, "Haichenbach"); + + let rocket = rocket::build().manage(db.clone()); + let rocket = crate::tera::config(rocket); + + let client = Client::tracked(rocket).await.unwrap(); + let login = client + .post("/auth") + .header(ContentType::Form) // Set the content type to form + .body("name=admin&password=admin"); // Add the form data to the request body; + login.dispatch().await; + + let req = client + .post("/admin/boat/1") + .header(ContentType::Form) + .body("name=Haichiii&amount_seats=1&location_id=1"); + let response = req.dispatch().await; + + assert_eq!(response.status(), Status::SeeOther); + assert_eq!( + response.headers().get("Location").next(), + Some("/admin/boat") + ); + + let flash_cookie = response + .cookies() + .get("_flash") + .expect("Expected flash cookie"); + + assert_eq!(flash_cookie.value(), "7:successSuccessfully updated boat"); + + let boat = Boat::find_by_id(&db, 1).await.unwrap(); + assert_eq!(boat.name, "Haichiii"); + } + + #[sqlx::test] + fn test_update_wrong_boat() { + let db = testdb!(); + + let rocket = rocket::build().manage(db.clone()); + let rocket = crate::tera::config(rocket); + + let client = Client::tracked(rocket).await.unwrap(); + let login = client + .post("/auth") + .header(ContentType::Form) // Set the content type to form + .body("name=admin&password=admin"); // Add the form data to the request body; + login.dispatch().await; + + let req = client + .post("/admin/boat/1337") + .header(ContentType::Form) + .body("name=Haichiii&amount_seats=1&location_id=1"); + let response = req.dispatch().await; + + assert_eq!(response.status(), Status::SeeOther); + assert_eq!( + response.headers().get("Location").next(), + Some("/admin/boat") + ); + + let flash_cookie = response + .cookies() + .get("_flash") + .expect("Expected flash cookie"); + + assert_eq!(flash_cookie.value(), "5:errorBoat does not exist!"); + + let boat = Boat::find_by_id(&db, 1).await.unwrap(); + assert_eq!(boat.name, "Haichenbach"); + } + + #[sqlx::test] + fn test_update_wrong_foreign() { + let db = testdb!(); + + let rocket = rocket::build().manage(db.clone()); + let rocket = crate::tera::config(rocket); + + let client = Client::tracked(rocket).await.unwrap(); + let login = client + .post("/auth") + .header(ContentType::Form) // Set the content type to form + .body("name=admin&password=admin"); // Add the form data to the request body; + login.dispatch().await; + + let req = client + .post("/admin/boat/1") + .header(ContentType::Form) + .body("name=Haichiii&amount_seats=1&location_id=999"); + let response = req.dispatch().await; + + assert_eq!(response.status(), Status::SeeOther); + assert_eq!( + response.headers().get("Location").next(), + Some("/admin/boat") + ); + + let flash_cookie = response + .cookies() + .get("_flash") + .expect("Expected flash cookie"); + + assert_eq!( + flash_cookie.value(), + "5:errorerror returned from database: (code: 787) FOREIGN KEY constraint failed" + ); + } + + #[sqlx::test] + fn test_succ_create() { + let db = testdb!(); + + let rocket = rocket::build().manage(db.clone()); + let rocket = crate::tera::config(rocket); + + let client = Client::tracked(rocket).await.unwrap(); + let login = client + .post("/auth") + .header(ContentType::Form) // Set the content type to form + .body("name=admin&password=admin"); // Add the form data to the request body; + login.dispatch().await; + + let req = client + .post("/admin/boat/new") + .header(ContentType::Form) + .body("name=completely-new-boat&amount_seats=1&location_id=1"); + let response = req.dispatch().await; + + assert_eq!(response.status(), Status::SeeOther); + assert_eq!( + response.headers().get("Location").next(), + Some("/admin/boat") + ); + + let flash_cookie = response + .cookies() + .get("_flash") + .expect("Expected flash cookie"); + + assert_eq!(flash_cookie.value(), "7:successSuccessfully created boat"); + + let boat = Boat::find_by_id(&db, 6).await.unwrap(); + assert_eq!(boat.name, "completely-new-boat"); + } + + #[sqlx::test] + fn test_create_db_error() { + let db = testdb!(); + + let rocket = rocket::build().manage(db.clone()); + let rocket = crate::tera::config(rocket); + + let client = Client::tracked(rocket).await.unwrap(); + let login = client + .post("/auth") + .header(ContentType::Form) // Set the content type to form + .body("name=admin&password=admin"); // Add the form data to the request body; + login.dispatch().await; + + let req = client + .post("/admin/boat/new") + .header(ContentType::Form) + .body("name=Haichenbach&amount_seats=1&location_id=1"); + let response = req.dispatch().await; + + assert_eq!(response.status(), Status::SeeOther); + assert_eq!( + response.headers().get("Location").next(), + Some("/admin/boat") + ); + + let flash_cookie = response + .cookies() + .get("_flash") + .expect("Expected flash cookie"); + + assert_eq!( + flash_cookie.value(), + "5:errorerror returned from database: (code: 2067) UNIQUE constraint failed: boat.name" + ); + } +}