extern crate mozaic4_backend; use diesel; use diesel::prelude::*; use mozaic4_backend::DbConn; use rocket::http::{ContentType, Header, Status}; use rocket::local::asynchronous::Client; // We use a lock to synchronize between tests so DB operations don't collide. // For now. In the future, we'll have a nice way to run each test in a DB // transaction so we can regain concurrency. static DB_LOCK: parking_lot::Mutex<()> = parking_lot::const_mutex(()); async fn reset_db(db: &DbConn) { db.run(|conn| { diesel::sql_query("TRUNCATE TABLE users, sessions") .execute(conn) .expect("drop all tables"); }) .await } macro_rules! run_test { (|$client:ident, $conn:ident| $block:expr) => {{ let _lock = DB_LOCK.lock(); rocket::async_test(async move { let $client = Client::tracked(mozaic4_backend::rocket()) .await .expect("Rocket client"); let db = mozaic4_backend::DbConn::get_one($client.rocket()).await; let $conn = db.expect("failed to get database connection for testing"); reset_db(&$conn).await; $block }) }}; } pub struct BearerAuth { token: String, } impl BearerAuth { pub fn new(token: String) -> Self { Self { token } } } impl<'a> Into> for BearerAuth { fn into(self) -> Header<'a> { Header::new("Authorization", format!("Bearer {}", self.token)) } } #[test] fn test_registration() { run_test!(|client, _conn| { let response = client .post("/register") .header(ContentType::JSON) .body(r#"{"username": "piepkonijn", "password": "geheim123"}"#) .dispatch() .await; assert_eq!(response.status(), Status::Ok); assert_eq!(response.content_type(), Some(ContentType::JSON)); let response = client .post("/login") .header(ContentType::JSON) .body(r#"{"username": "piepkonijn", "password": "geheim123"}"#) .dispatch() .await; assert_eq!(response.status(), Status::Ok); let token = response.into_string().await.unwrap(); let response = client .get("/users/me") .header(BearerAuth::new(token)) .dispatch() .await; assert_eq!(response.status(), Status::Ok); assert_eq!(response.content_type(), Some(ContentType::JSON)); let resp = response.into_string().await.unwrap(); let json: serde_json::Value = serde_json::from_str(&resp).unwrap(); assert_eq!(json["username"], "piepkonijn"); }); } #[test] fn test_reject_invalid_credentials() { run_test!(|client, _conn| { let response = client .post("/login") .header(ContentType::JSON) .body(r#"{"username": "piepkonijn", "password": "letmeinplease"}"#) .dispatch() .await; assert_eq!(response.status(), Status::Forbidden); // assert_eq!(response.content_type(), Some(ContentType::JSON)); }); }