diff --git a/tests/common/client.rs b/tests/common/client.rs index 687b5044..c9c22d2e 100644 --- a/tests/common/client.rs +++ b/tests/common/client.rs @@ -8,7 +8,9 @@ use super::contexts::category::forms::{AddCategoryForm, DeleteCategoryForm}; use super::contexts::tag::forms::{AddTagForm, DeleteTagForm}; use super::contexts::torrent::forms::UpdateTorrentFrom; use super::contexts::torrent::requests::InfoHash; -use super::contexts::user::forms::{LoginForm, RegistrationForm, TokenRenewalForm, TokenVerificationForm, Username}; +use super::contexts::user::forms::{ + ChangePasswordForm, LoginForm, RegistrationForm, TokenRenewalForm, TokenVerificationForm, Username, +}; use super::http::{Query, ReqwestQuery}; use super::responses::{self, BinaryResponse, TextResponse}; @@ -158,6 +160,12 @@ impl Client { self.http_client.post("/user/login", ®istration_form).await } + pub async fn change_password(&self, username: Username, change_password_form: ChangePasswordForm) -> TextResponse { + self.http_client + .post(&format!("/user/{}/change-password", &username.value), &change_password_form) + .await + } + pub async fn verify_token(&self, token_verification_form: TokenVerificationForm) -> TextResponse { self.http_client.post("/user/token/verify", &token_verification_form).await } @@ -351,13 +359,9 @@ impl Http { } fn base_url(&self, path: &str) -> String { - let url = format!( + format!( "http://{}/{}{path}", // DevSkim: ignore DS137138 &self.connection_info.bind_address, &self.connection_info.base_path - ); - - println!("URL: {url}"); - - url + ) } } diff --git a/tests/common/contexts/user/asserts.rs b/tests/common/contexts/user/asserts.rs index dfa5352b..959d0931 100644 --- a/tests/common/contexts/user/asserts.rs +++ b/tests/common/contexts/user/asserts.rs @@ -12,13 +12,13 @@ pub fn assert_added_user_response(response: &TextResponse) { assert_json_ok_response(response); } -pub fn assert_successful_login_response(response: &TextResponse, registered_user: &RegistrationForm) { +pub fn assert_successful_login_response(response: &TextResponse, username: &str) { let successful_login_response: SuccessfulLoginResponse = serde_json::from_str(&response.body) .unwrap_or_else(|_| panic!("response {:#?} should be a SuccessfulLoginResponse", response.body)); let logged_in_user = successful_login_response.data; - assert_eq!(logged_in_user.username, registered_user.username); + assert_eq!(logged_in_user.username, username); assert_json_ok_response(response); } diff --git a/tests/common/contexts/user/fixtures.rs b/tests/common/contexts/user/fixtures.rs index fea39e7f..4d5ce357 100644 --- a/tests/common/contexts/user/fixtures.rs +++ b/tests/common/contexts/user/fixtures.rs @@ -2,13 +2,19 @@ use rand::Rng; use crate::common::contexts::user::forms::RegistrationForm; +/// Default password used in tests +pub const DEFAULT_PASSWORD: &str = "password"; + +/// Sample valid password used in tests +pub const VALID_PASSWORD: &str = "12345678"; + pub fn random_user_registration_form() -> RegistrationForm { let user_id = random_user_id(); RegistrationForm { username: format!("username_{user_id}"), email: Some(format!("email_{user_id}@email.com")), - password: "password".to_string(), - confirm_password: "password".to_string(), + password: DEFAULT_PASSWORD.to_string(), + confirm_password: DEFAULT_PASSWORD.to_string(), } } diff --git a/tests/common/contexts/user/forms.rs b/tests/common/contexts/user/forms.rs index 359252a8..bc2e9a1b 100644 --- a/tests/common/contexts/user/forms.rs +++ b/tests/common/contexts/user/forms.rs @@ -35,3 +35,10 @@ impl Username { Self { value } } } + +#[derive(Serialize)] +pub struct ChangePasswordForm { + pub current_password: String, + pub password: String, + pub confirm_password: String, +} diff --git a/tests/e2e/web/api/v1/contexts/user/contract.rs b/tests/e2e/web/api/v1/contexts/user/contract.rs index 809a2cb9..14ea0490 100644 --- a/tests/e2e/web/api/v1/contexts/user/contract.rs +++ b/tests/e2e/web/api/v1/contexts/user/contract.rs @@ -58,7 +58,10 @@ mod authentication { use crate::common::contexts::user::asserts::{ assert_successful_login_response, assert_token_renewal_response, assert_token_verified_response, }; - use crate::common::contexts::user::forms::{LoginForm, TokenRenewalForm, TokenVerificationForm}; + use crate::common::contexts::user::fixtures::{DEFAULT_PASSWORD, VALID_PASSWORD}; + use crate::common::contexts::user::forms::{ + ChangePasswordForm, LoginForm, TokenRenewalForm, TokenVerificationForm, Username, + }; use crate::e2e::environment::TestEnv; use crate::e2e::web::api::v1::contexts::user::steps::{new_logged_in_user, new_registered_user}; @@ -78,7 +81,41 @@ mod authentication { }) .await; - assert_successful_login_response(&response, ®istered_user); + assert_successful_login_response(&response, ®istered_user.username); + } + + #[tokio::test] + async fn it_should_allow_logged_in_users_to_change_their_passwords() { + let mut env = TestEnv::new(); + env.start(api::Version::V1).await; + + let logged_in_user = new_logged_in_user(&env).await; + + let client = Client::authenticated(&env.server_socket_addr().unwrap(), &logged_in_user.token); + + let new_password = VALID_PASSWORD.to_string(); + + let response = client + .change_password( + Username::new(logged_in_user.username.clone()), + ChangePasswordForm { + current_password: DEFAULT_PASSWORD.to_string(), + password: new_password.clone(), + confirm_password: new_password.clone(), + }, + ) + .await; + + assert_eq!(response.status, 200); + + let response = client + .login_user(LoginForm { + login: logged_in_user.username.clone(), + password: new_password, + }) + .await; + + assert_successful_login_response(&response, &logged_in_user.username); } #[tokio::test]