test: move application tests to tests/
test_support/test_helpers -> tests/support; watched_at unified w/ domain test_watched_at (2024-03-15). Kept inline: users::diary_filter tests (feed_sort_to_direction_all_variants, paged_user_filter_builds_correctly) - pub(super) helpers in private module. Dropped stale never-compiled users/tests/get_users.rs (old execute signature).
This commit is contained in:
@@ -52,7 +52,3 @@ pub async fn execute(deps: &LoginDeps, query: LoginCommand) -> Result<LoginResul
|
||||
role: user.role().clone(),
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "tests/login.rs"]
|
||||
mod tests;
|
||||
|
||||
@@ -5,7 +5,3 @@ use crate::auth::deps::LogoutDeps;
|
||||
pub async fn execute(deps: &LogoutDeps, refresh_token: &str) -> Result<(), DomainError> {
|
||||
deps.refresh_session.revoke(refresh_token).await
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "tests/logout.rs"]
|
||||
mod tests;
|
||||
|
||||
@@ -50,7 +50,3 @@ pub async fn execute(
|
||||
expires_at: generated.expires_at,
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "tests/refresh.rs"]
|
||||
mod tests;
|
||||
|
||||
@@ -32,7 +32,3 @@ pub async fn execute(deps: &RegisterDeps, cmd: RegisterCommand) -> Result<(), Do
|
||||
.save(&User::new(email, username, hash, cmd.role))
|
||||
.await
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "tests/register.rs"]
|
||||
mod tests;
|
||||
|
||||
@@ -44,7 +44,3 @@ pub async fn execute(
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "tests/register_and_login.rs"]
|
||||
mod tests;
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
use crate::test_support::{login_command, register_command};
|
||||
use std::sync::Arc;
|
||||
|
||||
use domain::testing::InMemoryStore;
|
||||
|
||||
use crate::{
|
||||
auth::{
|
||||
commands::RegisterCommand,
|
||||
deps::{LoginDeps, RegisterDeps},
|
||||
login, register,
|
||||
},
|
||||
test_helpers::TestContextBuilder,
|
||||
};
|
||||
|
||||
async fn setup_user(b: &TestContextBuilder, email: &str, password: &str) {
|
||||
let deps = RegisterDeps {
|
||||
user: b.user_repo.clone(),
|
||||
password_hasher: b.password_hasher.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
register::execute(
|
||||
&deps,
|
||||
RegisterCommand {
|
||||
password: password.to_string(),
|
||||
..register_command(email, "testuser")
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_login_valid_credentials_returns_token() {
|
||||
let users = InMemoryStore::new();
|
||||
let b = TestContextBuilder::new().with_users(Arc::clone(&users) as _);
|
||||
setup_user(&b, "carol@example.com", "secret123").await;
|
||||
|
||||
let deps = LoginDeps {
|
||||
user: b.user_repo.clone(),
|
||||
password_hasher: b.password_hasher.clone(),
|
||||
auth: b.auth_service.clone(),
|
||||
refresh_session: b.refresh_session_repo.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
let result = login::execute(&deps, login_command("carol@example.com", "secret123"))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert!(!result.token.is_empty());
|
||||
assert!(!result.refresh_token.is_empty());
|
||||
assert_eq!(result.email, "carol@example.com");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_login_wrong_password_fails() {
|
||||
let users = InMemoryStore::new();
|
||||
let b = TestContextBuilder::new().with_users(Arc::clone(&users) as _);
|
||||
setup_user(&b, "dave@example.com", "correct_password").await;
|
||||
|
||||
let deps = LoginDeps {
|
||||
user: b.user_repo.clone(),
|
||||
password_hasher: b.password_hasher.clone(),
|
||||
auth: b.auth_service.clone(),
|
||||
refresh_session: b.refresh_session_repo.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
let result = login::execute(&deps, login_command("dave@example.com", "wrong_password")).await;
|
||||
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_login_unknown_email_fails() {
|
||||
let b = TestContextBuilder::new();
|
||||
let deps = LoginDeps {
|
||||
user: b.user_repo.clone(),
|
||||
password_hasher: b.password_hasher.clone(),
|
||||
auth: b.auth_service.clone(),
|
||||
refresh_session: b.refresh_session_repo.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
let result = login::execute(&deps, login_command("nobody@example.com", "anything")).await;
|
||||
|
||||
assert!(result.is_err());
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
use crate::test_support::{login_command, register_command};
|
||||
use std::sync::Arc;
|
||||
|
||||
use domain::testing::InMemoryStore;
|
||||
|
||||
use crate::{
|
||||
auth::{
|
||||
deps::{LoginDeps, LogoutDeps, RefreshDeps, RegisterDeps},
|
||||
login, logout, refresh, register,
|
||||
},
|
||||
test_helpers::TestContextBuilder,
|
||||
};
|
||||
|
||||
#[tokio::test]
|
||||
async fn logout_revokes_refresh_token() {
|
||||
let users = InMemoryStore::new();
|
||||
let b = TestContextBuilder::new().with_users(Arc::clone(&users) as _);
|
||||
|
||||
let reg_deps = RegisterDeps {
|
||||
user: b.user_repo.clone(),
|
||||
password_hasher: b.password_hasher.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
register::execute(®_deps, register_command("bob@example.com", "bob"))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let login_deps = LoginDeps {
|
||||
user: b.user_repo.clone(),
|
||||
password_hasher: b.password_hasher.clone(),
|
||||
auth: b.auth_service.clone(),
|
||||
refresh_session: b.refresh_session_repo.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
let login_result = login::execute(&login_deps, login_command("bob@example.com", "password123"))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let logout_deps = LogoutDeps {
|
||||
refresh_session: b.refresh_session_repo.clone(),
|
||||
};
|
||||
logout::execute(&logout_deps, &login_result.refresh_token)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let refresh_deps = RefreshDeps {
|
||||
refresh_session: b.refresh_session_repo.clone(),
|
||||
auth: b.auth_service.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
let refresh_attempt = refresh::execute(&refresh_deps, &login_result.refresh_token).await;
|
||||
assert!(refresh_attempt.is_err());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn logout_with_unknown_token_succeeds() {
|
||||
let b = TestContextBuilder::new();
|
||||
let logout_deps = LogoutDeps {
|
||||
refresh_session: b.refresh_session_repo.clone(),
|
||||
};
|
||||
let result = logout::execute(&logout_deps, "nonexistent-token").await;
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
use crate::test_support::{login_command, register_command};
|
||||
use std::sync::Arc;
|
||||
|
||||
use domain::testing::InMemoryStore;
|
||||
|
||||
use crate::{
|
||||
auth::{
|
||||
deps::{LoginDeps, RefreshDeps, RegisterDeps},
|
||||
login, refresh, register,
|
||||
},
|
||||
test_helpers::TestContextBuilder,
|
||||
};
|
||||
|
||||
async fn login_user(b: &TestContextBuilder) -> login::LoginResult {
|
||||
let reg_deps = RegisterDeps {
|
||||
user: b.user_repo.clone(),
|
||||
password_hasher: b.password_hasher.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
register::execute(®_deps, register_command("alice@example.com", "alice"))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let login_deps = LoginDeps {
|
||||
user: b.user_repo.clone(),
|
||||
password_hasher: b.password_hasher.clone(),
|
||||
auth: b.auth_service.clone(),
|
||||
refresh_session: b.refresh_session_repo.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
login::execute(
|
||||
&login_deps,
|
||||
login_command("alice@example.com", "password123"),
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn refresh_returns_new_tokens() {
|
||||
let users = InMemoryStore::new();
|
||||
let b = TestContextBuilder::new().with_users(Arc::clone(&users) as _);
|
||||
let login_result = login_user(&b).await;
|
||||
|
||||
let deps = RefreshDeps {
|
||||
refresh_session: b.refresh_session_repo.clone(),
|
||||
auth: b.auth_service.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
let result = refresh::execute(&deps, &login_result.refresh_token)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert!(!result.token.is_empty());
|
||||
assert!(!result.refresh_token.is_empty());
|
||||
assert_ne!(result.refresh_token, login_result.refresh_token);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn refresh_rotates_token_old_one_invalid() {
|
||||
let users = InMemoryStore::new();
|
||||
let b = TestContextBuilder::new().with_users(Arc::clone(&users) as _);
|
||||
let login_result = login_user(&b).await;
|
||||
let old_token = login_result.refresh_token.clone();
|
||||
|
||||
let deps = RefreshDeps {
|
||||
refresh_session: b.refresh_session_repo.clone(),
|
||||
auth: b.auth_service.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
refresh::execute(&deps, &old_token).await.unwrap();
|
||||
|
||||
let retry = refresh::execute(&deps, &old_token).await;
|
||||
assert!(retry.is_err());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn refresh_with_new_token_works() {
|
||||
let users = InMemoryStore::new();
|
||||
let b = TestContextBuilder::new().with_users(Arc::clone(&users) as _);
|
||||
let login_result = login_user(&b).await;
|
||||
|
||||
let deps = RefreshDeps {
|
||||
refresh_session: b.refresh_session_repo.clone(),
|
||||
auth: b.auth_service.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
let first = refresh::execute(&deps, &login_result.refresh_token)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let second = refresh::execute(&deps, &first.refresh_token).await.unwrap();
|
||||
|
||||
assert!(!second.token.is_empty());
|
||||
assert_ne!(second.refresh_token, first.refresh_token);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn refresh_with_unknown_token_fails() {
|
||||
let b = TestContextBuilder::new();
|
||||
let deps = RefreshDeps {
|
||||
refresh_session: b.refresh_session_repo.clone(),
|
||||
auth: b.auth_service.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
let result = refresh::execute(&deps, "nonexistent-token").await;
|
||||
assert!(result.is_err());
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
use crate::test_support::register_command;
|
||||
use std::sync::Arc;
|
||||
|
||||
use domain::ports::UserRepository;
|
||||
use domain::testing::InMemoryStore;
|
||||
use domain::value_objects::Email;
|
||||
|
||||
use crate::{
|
||||
auth::{commands::RegisterCommand, deps::RegisterDeps, register},
|
||||
test_helpers::TestContextBuilder,
|
||||
};
|
||||
|
||||
fn cmd(email: &str) -> RegisterCommand {
|
||||
register_command(email, "alice")
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_register_creates_user() {
|
||||
let users = InMemoryStore::new();
|
||||
let b = TestContextBuilder::new().with_users(Arc::clone(&users) as _);
|
||||
let deps = RegisterDeps {
|
||||
user: b.user_repo.clone(),
|
||||
password_hasher: b.password_hasher.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
|
||||
register::execute(&deps, cmd("alice@example.com"))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let email = Email::new("alice@example.com".into()).unwrap();
|
||||
let user = users.find_by_email(&email).await.unwrap().unwrap();
|
||||
assert_eq!(user.email().value(), "alice@example.com");
|
||||
assert!(user.password_hash().value().starts_with("hashed:"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_register_duplicate_email_fails() {
|
||||
let users = InMemoryStore::new();
|
||||
let b = TestContextBuilder::new().with_users(Arc::clone(&users) as _);
|
||||
let deps = RegisterDeps {
|
||||
user: b.user_repo.clone(),
|
||||
password_hasher: b.password_hasher.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
|
||||
register::execute(&deps, cmd("bob@example.com"))
|
||||
.await
|
||||
.unwrap();
|
||||
let result = register::execute(&deps, cmd("bob@example.com")).await;
|
||||
assert!(result.is_err(), "duplicate email should fail");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_register_short_password_fails() {
|
||||
let b = TestContextBuilder::new();
|
||||
let deps = RegisterDeps {
|
||||
user: b.user_repo.clone(),
|
||||
password_hasher: b.password_hasher.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
let result = register::execute(
|
||||
&deps,
|
||||
RegisterCommand {
|
||||
password: "short".to_string(),
|
||||
..register_command("x@y.com", "testuser")
|
||||
},
|
||||
)
|
||||
.await;
|
||||
let err = result.unwrap_err().to_string();
|
||||
assert!(
|
||||
err.contains("8 characters"),
|
||||
"expected password length error, got: {err}"
|
||||
);
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
use crate::auth::commands::RegisterAndLoginCommand;
|
||||
use crate::auth::deps::RegisterAndLoginDeps;
|
||||
use crate::auth::register_and_login;
|
||||
use crate::test_helpers::TestContextBuilder;
|
||||
|
||||
#[tokio::test]
|
||||
async fn registers_and_returns_token() {
|
||||
let b = TestContextBuilder::new();
|
||||
let deps = RegisterAndLoginDeps {
|
||||
user: b.user_repo.clone(),
|
||||
password_hasher: b.password_hasher.clone(),
|
||||
auth: b.auth_service.clone(),
|
||||
refresh_session: b.refresh_session_repo.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
|
||||
let result = register_and_login::execute(
|
||||
&deps,
|
||||
RegisterAndLoginCommand {
|
||||
email: "new@example.com".into(),
|
||||
username: "newuser".into(),
|
||||
password: "password123".into(),
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert!(!result.token.is_empty());
|
||||
assert_eq!(result.email, "new@example.com");
|
||||
}
|
||||
Reference in New Issue
Block a user