From 916b92a55765b0548559a1c9113708694d9eaa5b Mon Sep 17 00:00:00 2001 From: Elad Kaplan Date: Mon, 16 Dec 2024 22:54:32 +0200 Subject: [PATCH] tests --- loco-new/base_template/src/models/users.rs | 8 +- .../base_template/tests/models/users.rs.t | 133 +++++++++--------- .../base_template/tests/requests/auth.rs.t | 53 ++++--- ...can_login_without_verify@auth_request.snap | 7 +- .../can_reset_password@auth_request.snap | 5 +- 5 files changed, 113 insertions(+), 93 deletions(-) diff --git a/loco-new/base_template/src/models/users.rs b/loco-new/base_template/src/models/users.rs index 23fc147eb..2855e1f9e 100644 --- a/loco-new/base_template/src/models/users.rs +++ b/loco-new/base_template/src/models/users.rs @@ -30,7 +30,7 @@ pub struct Validator { pub email: String, } -impl Validatable for super::_entities::users::ActiveModel { +impl Validatable for ActiveModel { fn validator(&self) -> Box { Box::new(Validator { name: self.name.as_ref().to_owned(), @@ -58,7 +58,7 @@ impl ActiveModelBehavior for super::_entities::users::ActiveModel { } #[async_trait] -impl Authenticable for super::_entities::users::Model { +impl Authenticable for Model { async fn find_by_api_key(db: &DatabaseConnection, api_key: &str) -> ModelResult { let user = users::Entity::find() .filter( @@ -76,7 +76,7 @@ impl Authenticable for super::_entities::users::Model { } } -impl super::_entities::users::Model { +impl Model { /// finds a user by the provided email /// /// # Errors @@ -263,7 +263,7 @@ impl super::_entities::users::Model { } } -impl super::_entities::users::ActiveModel { +impl ActiveModel { /// Sets the email verification information for the user and /// updates it in the database. /// diff --git a/loco-new/base_template/tests/models/users.rs.t b/loco-new/base_template/tests/models/users.rs.t index 86a27f498..16f845b6b 100644 --- a/loco-new/base_template/tests/models/users.rs.t +++ b/loco-new/base_template/tests/models/users.rs.t @@ -1,6 +1,6 @@ use chrono::{offset::Local, Duration}; use insta::assert_debug_snapshot; -use loco_rs::{model::ModelError, testing::prelude::*}; +use loco_rs::testing::prelude::*; use {{settings.module_name}}::{ app::App, models::users::{self, Model, RegisterParams}, @@ -22,15 +22,15 @@ macro_rules! configure_insta { async fn test_can_validate_model() { configure_insta!(); - let boot = boot_test::().await.unwrap(); + let boot = boot_test::().await.expect("Failed to boot test application"); - let res = users::ActiveModel { + let invalid_user = users::ActiveModel { name: ActiveValue::set("1".to_string()), email: ActiveValue::set("invalid-email".to_string()), ..Default::default() - } - .insert(&boot.app_context.db) - .await; + }; + + let res = invalid_user.insert(&boot.app_context.db).await; assert_debug_snapshot!(res); } @@ -40,13 +40,14 @@ async fn test_can_validate_model() { async fn can_create_with_password() { configure_insta!(); - let boot = boot_test::().await.unwrap(); + let boot = boot_test::().await.expect("Failed to boot test application"); let params = RegisterParams { email: "test@framework.com".to_string(), password: "1234".to_string(), name: "framework".to_string(), }; + let res = Model::create_with_password(&boot.app_context.db, ¶ms).await; insta::with_settings!({ @@ -55,16 +56,15 @@ async fn can_create_with_password() { assert_debug_snapshot!(res); }); } - #[tokio::test] #[serial] async fn handle_create_with_password_with_duplicate() { configure_insta!(); - let boot = boot_test::().await.unwrap(); - seed::(&boot.app_context.db).await.unwrap(); + let boot = boot_test::().await.expect("Failed to boot test application"); + seed::(&boot.app_context.db).await.expect("Failed to seed database"); - let new_user: Result = Model::create_with_password( + let new_user = Model::create_with_password( &boot.app_context.db, &RegisterParams { email: "user1@example.com".to_string(), @@ -73,6 +73,7 @@ async fn handle_create_with_password_with_duplicate() { }, ) .await; + assert_debug_snapshot!(new_user); } @@ -81,12 +82,11 @@ async fn handle_create_with_password_with_duplicate() { async fn can_find_by_email() { configure_insta!(); - let boot = boot_test::().await.unwrap(); - seed::(&boot.app_context.db).await.unwrap(); + let boot = boot_test::().await.expect("Failed to boot test application"); + seed::(&boot.app_context.db).await.expect("Failed to seed database"); let existing_user = Model::find_by_email(&boot.app_context.db, "user1@example.com").await; - let non_existing_user_results = - Model::find_by_email(&boot.app_context.db, "un@existing-email.com").await; + let non_existing_user_results = Model::find_by_email(&boot.app_context.db, "un@existing-email.com").await; assert_debug_snapshot!(existing_user); assert_debug_snapshot!(non_existing_user_results); @@ -97,13 +97,11 @@ async fn can_find_by_email() { async fn can_find_by_pid() { configure_insta!(); - let boot = boot_test::().await.unwrap(); - seed::(&boot.app_context.db).await.unwrap(); + let boot = boot_test::().await.expect("Failed to boot test application"); + seed::(&boot.app_context.db).await.expect("Failed to seed database"); - let existing_user = - Model::find_by_pid(&boot.app_context.db, "11111111-1111-1111-1111-111111111111").await; - let non_existing_user_results = - Model::find_by_pid(&boot.app_context.db, "23232323-2323-2323-2323-232323232323").await; + let existing_user = Model::find_by_pid(&boot.app_context.db, "11111111-1111-1111-1111-111111111111").await; + let non_existing_user_results = Model::find_by_pid(&boot.app_context.db, "23232323-2323-2323-2323-232323232323").await; assert_debug_snapshot!(existing_user); assert_debug_snapshot!(non_existing_user_results); @@ -114,115 +112,122 @@ async fn can_find_by_pid() { async fn can_verification_token() { configure_insta!(); - let boot = boot_test::().await.unwrap(); - seed::(&boot.app_context.db).await.unwrap(); + let boot = boot_test::().await.expect("Failed to boot test application"); + seed::(&boot.app_context.db).await.expect("Failed to seed database"); let user = Model::find_by_pid(&boot.app_context.db, "11111111-1111-1111-1111-111111111111") .await - .unwrap(); + .expect("Failed to find user by PID"); - assert!(user.email_verification_sent_at.is_none()); - assert!(user.email_verification_token.is_none()); + assert!(user.email_verification_sent_at.is_none(), "Expected no email verification sent timestamp"); + assert!(user.email_verification_token.is_none(), "Expected no email verification token"); - assert!(user + let result = user .into_active_model() .set_email_verification_sent(&boot.app_context.db) - .await - .is_ok()); + .await; + + assert!(result.is_ok(), "Failed to set email verification sent"); let user = Model::find_by_pid(&boot.app_context.db, "11111111-1111-1111-1111-111111111111") .await - .unwrap(); + .expect("Failed to find user by PID after setting verification sent"); - assert!(user.email_verification_sent_at.is_some()); - assert!(user.email_verification_token.is_some()); + assert!(user.email_verification_sent_at.is_some(), "Expected email verification sent timestamp to be present"); + assert!(user.email_verification_token.is_some(), "Expected email verification token to be present"); } + #[tokio::test] #[serial] async fn can_set_forgot_password_sent() { configure_insta!(); - let boot = boot_test::().await.unwrap(); - seed::(&boot.app_context.db).await.unwrap(); + let boot = boot_test::().await.expect("Failed to boot test application"); + seed::(&boot.app_context.db).await.expect("Failed to seed database"); let user = Model::find_by_pid(&boot.app_context.db, "11111111-1111-1111-1111-111111111111") .await - .unwrap(); + .expect("Failed to find user by PID"); - assert!(user.reset_sent_at.is_none()); - assert!(user.reset_token.is_none()); + assert!(user.reset_sent_at.is_none(), "Expected no reset sent timestamp"); + assert!(user.reset_token.is_none(), "Expected no reset token"); - assert!(user + let result = user .into_active_model() .set_forgot_password_sent(&boot.app_context.db) - .await - .is_ok()); + .await; + + assert!(result.is_ok(), "Failed to set forgot password sent"); let user = Model::find_by_pid(&boot.app_context.db, "11111111-1111-1111-1111-111111111111") .await - .unwrap(); + .expect("Failed to find user by PID after setting forgot password sent"); - assert!(user.reset_sent_at.is_some()); - assert!(user.reset_token.is_some()); + assert!(user.reset_sent_at.is_some(), "Expected reset sent timestamp to be present"); + assert!(user.reset_token.is_some(), "Expected reset token to be present"); } + #[tokio::test] #[serial] async fn can_verified() { configure_insta!(); - let boot = boot_test::().await.unwrap(); - seed::(&boot.app_context.db).await.unwrap(); + let boot = boot_test::().await.expect("Failed to boot test application"); + seed::(&boot.app_context.db).await.expect("Failed to seed database"); let user = Model::find_by_pid(&boot.app_context.db, "11111111-1111-1111-1111-111111111111") .await - .unwrap(); + .expect("Failed to find user by PID"); - assert!(user.email_verified_at.is_none()); + assert!(user.email_verified_at.is_none(), "Expected email to be unverified"); - assert!(user + let result = user .into_active_model() .verified(&boot.app_context.db) - .await - .is_ok()); + .await; + + assert!(result.is_ok(), "Failed to mark email as verified"); let user = Model::find_by_pid(&boot.app_context.db, "11111111-1111-1111-1111-111111111111") .await - .unwrap(); + .expect("Failed to find user by PID after verification"); - assert!(user.email_verified_at.is_some()); + assert!(user.email_verified_at.is_some(), "Expected email to be verified"); } + #[tokio::test] #[serial] async fn can_reset_password() { configure_insta!(); - let boot = boot_test::().await.unwrap(); - seed::(&boot.app_context.db).await.unwrap(); + let boot = boot_test::().await.expect("Failed to boot test application"); + seed::(&boot.app_context.db).await.expect("Failed to seed database"); let user = Model::find_by_pid(&boot.app_context.db, "11111111-1111-1111-1111-111111111111") .await - .unwrap(); + .expect("Failed to find user by PID"); - assert!(user.verify_password("12341234")); + assert!(user.verify_password("12341234"), "Password verification failed for original password"); - assert!(user + let result = user .clone() .into_active_model() .reset_password(&boot.app_context.db, "new-password") + .await; + + assert!(result.is_ok(), "Failed to reset password"); + + let user = Model::find_by_pid(&boot.app_context.db, "11111111-1111-1111-1111-111111111111") .await - .is_ok()); + .expect("Failed to find user by PID after password reset"); - assert!( - Model::find_by_pid(&boot.app_context.db, "11111111-1111-1111-1111-111111111111") - .await - .unwrap() - .verify_password("new-password") - ); + assert!(user.verify_password("new-password"), "Password verification failed for new password"); } + #[tokio::test] #[serial] async fn magic_link() { diff --git a/loco-new/base_template/tests/requests/auth.rs.t b/loco-new/base_template/tests/requests/auth.rs.t index 1661c8818..0240175ca 100644 --- a/loco-new/base_template/tests/requests/auth.rs.t +++ b/loco-new/base_template/tests/requests/auth.rs.t @@ -69,11 +69,13 @@ async fn can_login_with_verify(#[case] test_name: &str, #[case] password: &str) }); //Creating a new user - _ = request + let register_response = request .post("/api/auth/register") .json(®ister_payload) .await; + assert_eq!(register_response.status_code(), 200, "Register request should succeed"); + let user = users::Model::find_by_email(&ctx.db, email).await.unwrap(); let verify_payload = serde_json::json!({ "token": user.email_verification_token, @@ -90,11 +92,15 @@ async fn can_login_with_verify(#[case] test_name: &str, #[case] password: &str) .await; // Make sure email_verified_at is set - assert!(users::Model::find_by_email(&ctx.db, email) + let user = users::Model::find_by_email(&ctx.db, email) .await - .unwrap() - .email_verified_at - .is_some()); + .expect("Failed to find user by email"); + + assert!( + user.email_verified_at.is_some(), + "Expected the email to be verified, but it was not. User: {:?}", + user + ); with_settings!({ filters => cleanup_user_model() @@ -120,13 +126,15 @@ async fn can_login_without_verify() { }); //Creating a new user - _ = request + let register_response = request .post("/api/auth/register") .json(®ister_payload) .await; + assert_eq!(register_response.status_code(), 200, "Register request should succeed"); + //verify user request - let response = request + let login_response = request .post("/api/auth/login") .json(&serde_json::json!({ "email": email, @@ -134,10 +142,12 @@ async fn can_login_without_verify() { })) .await; + assert_eq!(login_response.status_code(), 200, "Login request should succeed"); + with_settings!({ filters => cleanup_user_model() }, { - assert_debug_snapshot!((response.status_code(), response.text())); + assert_debug_snapshot!(login_response.text()); }); }) .await; @@ -154,13 +164,21 @@ async fn can_reset_password() { let forgot_payload = serde_json::json!({ "email": login_data.user.email, }); - _ = request.post("/api/auth/forgot").json(&forgot_payload).await; + let forget_response = request.post("/api/auth/forgot").json(&forgot_payload).await; + assert_eq!(forget_response.status_code(), 200, "Forget request should succeed"); let user = users::Model::find_by_email(&ctx.db, &login_data.user.email) .await - .unwrap(); - assert!(user.reset_token.is_some()); - assert!(user.reset_sent_at.is_some()); + .expect("Failed to find user by email"); + + assert!( + user.reset_token.is_some(), + "Expected reset_token to be set, but it was None. User: {user:?}" + ); + assert!( + user.reset_sent_at.is_some(), + "Expected reset_sent_at to be set, but it was None. User: {user:?}" + ); let new_password = "new-password"; let reset_payload = serde_json::json!({ @@ -169,6 +187,7 @@ async fn can_reset_password() { }); let reset_response = request.post("/api/auth/reset").json(&reset_payload).await; + assert_eq!(reset_response.status_code(), 200, "Reset password request should succeed"); let user = users::Model::find_by_email(&ctx.db, &user.email) .await @@ -177,9 +196,9 @@ async fn can_reset_password() { assert!(user.reset_token.is_none()); assert!(user.reset_sent_at.is_none()); - assert_debug_snapshot!((reset_response.status_code(), reset_response.text())); + assert_debug_snapshot!(reset_response.text()); - let response = request + let login_response = request .post("/api/auth/login") .json(&serde_json::json!({ "email": user.email, @@ -187,7 +206,7 @@ async fn can_reset_password() { })) .await; - assert_eq!(response.status_code(), 200); + assert_eq!(login_response.status_code(), 200, "Login request should succeed"); let deliveries = ctx.mailer.unwrap().deliveries(); assert_eq!(deliveries.count, 2, "Exactly one email should be sent"); @@ -214,6 +233,8 @@ async fn can_get_current_user() { .add_header(auth_key, auth_value) .await; + assert_eq!(response.status_code(), 200, "Current request should succeed"); + with_settings!({ filters => cleanup_user_model() }, { @@ -234,7 +255,7 @@ async fn can_auth_with_magic_link() { "email": "user1@example.com", }); let response = request.post("/api/auth/magic-link").json(&payload).await; - assert_eq!(response.status_code(), 200, "Magic link request should succeed"); + assert_eq!(response.status_code(), 200, "Magic link request should succeed"); let deliveries = ctx.mailer.unwrap().deliveries(); assert_eq!(deliveries.count, 1, "Exactly one email should be sent"); diff --git a/loco-new/base_template/tests/requests/snapshots/can_login_without_verify@auth_request.snap b/loco-new/base_template/tests/requests/snapshots/can_login_without_verify@auth_request.snap index ef54ba671..1fac2fd22 100644 --- a/loco-new/base_template/tests/requests/snapshots/can_login_without_verify@auth_request.snap +++ b/loco-new/base_template/tests/requests/snapshots/can_login_without_verify@auth_request.snap @@ -1,8 +1,5 @@ --- source: tests/requests/auth.rs -expression: "(response.status_code(), response.text())" +expression: login_response.text() --- -( - 200, - "{\"token\":\"TOKEN\",\"pid\":\"PID\",\"name\":\"loco\",\"is_verified\":false}", -) +"{\"token\":\"TOKEN\",\"pid\":\"PID\",\"name\":\"loco\",\"is_verified\":false}" diff --git a/loco-new/base_template/tests/requests/snapshots/can_reset_password@auth_request.snap b/loco-new/base_template/tests/requests/snapshots/can_reset_password@auth_request.snap index be6838d35..d42607978 100644 --- a/loco-new/base_template/tests/requests/snapshots/can_reset_password@auth_request.snap +++ b/loco-new/base_template/tests/requests/snapshots/can_reset_password@auth_request.snap @@ -2,7 +2,4 @@ source: tests/requests/auth.rs expression: "(reset_response.status_code(), reset_response.text())" --- -( - 200, - "null", -) +"null" \ No newline at end of file