refactor(users): GetProfileDeps, UpdateProfileDeps, scoped Arc deps

This commit is contained in:
2026-06-11 22:47:17 +02:00
parent 7bf5c47f5b
commit 61980b0cfb
18 changed files with 296 additions and 145 deletions

View File

@@ -15,9 +15,9 @@ use crate::{
#[tokio::test]
async fn returns_profile_for_existing_user() {
let users = InMemoryUserRepository::new();
let ctx = TestContextBuilder::new()
.with_users(Arc::clone(&users) as _)
.build();
let b = TestContextBuilder::new().with_users(Arc::clone(&users) as _);
let user_repo = b.user_repo.clone();
let ctx = b.build();
register::execute(
&ctx,
@@ -38,7 +38,7 @@ async fn returns_profile_for_existing_user() {
.unwrap();
let profile = get_current_profile::execute(
&ctx,
user_repo,
GetCurrentProfileQuery {
user_id: user.id().value(),
},
@@ -51,10 +51,11 @@ async fn returns_profile_for_existing_user() {
#[tokio::test]
async fn fails_for_nonexistent_user() {
let ctx = TestContextBuilder::new().build();
let b = TestContextBuilder::new();
let user_repo = b.user_repo.clone();
let result = get_current_profile::execute(
&ctx,
user_repo,
GetCurrentProfileQuery {
user_id: Uuid::new_v4(),
},
@@ -89,12 +90,11 @@ async fn returns_profile_with_avatar_banner_and_fields() {
);
users.store.lock().unwrap().insert(uid.value(), user);
let ctx = TestContextBuilder::new()
.with_users(Arc::clone(&users) as _)
.build();
let b = TestContextBuilder::new().with_users(Arc::clone(&users) as _);
let user_repo = b.user_repo.clone();
let profile = get_current_profile::execute(
&ctx,
user_repo,
GetCurrentProfileQuery {
user_id: uid.value(),
},

View File

@@ -4,12 +4,28 @@ use domain::value_objects::Email;
use crate::auth::commands::RegisterCommand;
use crate::auth::register;
use crate::test_helpers::TestContextBuilder;
use crate::users::deps::GetProfileDeps;
use crate::users::get_profile;
use crate::users::queries::{GetUserProfileQuery, ProfileView};
fn default_deps() -> GetProfileDeps {
let b = TestContextBuilder::new();
GetProfileDeps {
stats: b.stats_repo.clone(),
diary: b.diary_repo.clone(),
social_query: b.social_query.clone(),
}
}
#[tokio::test]
async fn returns_profile_with_empty_stats() {
let ctx = TestContextBuilder::new().build();
let b = TestContextBuilder::new();
let deps = GetProfileDeps {
stats: b.stats_repo.clone(),
diary: b.diary_repo.clone(),
social_query: b.social_query.clone(),
};
let ctx = b.build();
register::execute(
&ctx,
@@ -28,7 +44,7 @@ async fn returns_profile_with_empty_stats() {
let uid = user.id().value();
let result = get_profile::execute(
&ctx,
&deps,
GetUserProfileQuery {
user_id: uid,
view: ProfileView::Recent,
@@ -47,7 +63,13 @@ async fn returns_profile_with_empty_stats() {
#[tokio::test]
async fn returns_history_view() {
let ctx = TestContextBuilder::new().build();
let b = TestContextBuilder::new();
let deps = GetProfileDeps {
stats: b.stats_repo.clone(),
diary: b.diary_repo.clone(),
social_query: b.social_query.clone(),
};
let ctx = b.build();
register::execute(
&ctx,
@@ -66,7 +88,7 @@ async fn returns_history_view() {
let uid = user.id().value();
let result = get_profile::execute(
&ctx,
&deps,
GetUserProfileQuery {
user_id: uid,
view: ProfileView::History,
@@ -87,7 +109,13 @@ async fn returns_history_view() {
#[tokio::test]
async fn returns_trends_view() {
let ctx = TestContextBuilder::new().build();
let b = TestContextBuilder::new();
let deps = GetProfileDeps {
stats: b.stats_repo.clone(),
diary: b.diary_repo.clone(),
social_query: b.social_query.clone(),
};
let ctx = b.build();
register::execute(
&ctx,
@@ -106,7 +134,7 @@ async fn returns_trends_view() {
let uid = user.id().value();
let result = get_profile::execute(
&ctx,
&deps,
GetUserProfileQuery {
user_id: uid,
view: ProfileView::Trends,
@@ -127,7 +155,13 @@ async fn returns_trends_view() {
#[tokio::test]
async fn returns_ratings_view() {
let ctx = TestContextBuilder::new().build();
let b = TestContextBuilder::new();
let deps = GetProfileDeps {
stats: b.stats_repo.clone(),
diary: b.diary_repo.clone(),
social_query: b.social_query.clone(),
};
let ctx = b.build();
register::execute(
&ctx,
@@ -146,7 +180,7 @@ async fn returns_ratings_view() {
let uid = user.id().value();
let result = get_profile::execute(
&ctx,
&deps,
GetUserProfileQuery {
user_id: uid,
view: ProfileView::Ratings,
@@ -165,7 +199,13 @@ async fn returns_ratings_view() {
#[tokio::test]
async fn returns_recent_with_search() {
let ctx = TestContextBuilder::new().build();
let b = TestContextBuilder::new();
let deps = GetProfileDeps {
stats: b.stats_repo.clone(),
diary: b.diary_repo.clone(),
social_query: b.social_query.clone(),
};
let ctx = b.build();
register::execute(
&ctx,
@@ -184,7 +224,7 @@ async fn returns_recent_with_search() {
let uid = user.id().value();
let result = get_profile::execute(
&ctx,
&deps,
GetUserProfileQuery {
user_id: uid,
view: ProfileView::Recent,
@@ -203,7 +243,13 @@ async fn returns_recent_with_search() {
#[tokio::test]
async fn non_own_profile_skips_pending_followers() {
let ctx = TestContextBuilder::new().build();
let b = TestContextBuilder::new();
let deps = GetProfileDeps {
stats: b.stats_repo.clone(),
diary: b.diary_repo.clone(),
social_query: b.social_query.clone(),
};
let ctx = b.build();
register::execute(
&ctx,
@@ -222,7 +268,7 @@ async fn non_own_profile_skips_pending_followers() {
let uid = user.id().value();
let result = get_profile::execute(
&ctx,
&deps,
GetUserProfileQuery {
user_id: uid,
view: ProfileView::Recent,

View File

@@ -4,9 +4,10 @@ use crate::{test_helpers::TestContextBuilder, users::get_settings};
#[tokio::test]
async fn returns_default_settings() {
let ctx = TestContextBuilder::new().build();
let b = TestContextBuilder::new();
let user_settings = b.user_settings_repo.clone();
let settings = get_settings::execute(&ctx, Uuid::nil()).await.unwrap();
let settings = get_settings::execute(user_settings, Uuid::nil()).await.unwrap();
assert!(!settings.federate_goals());
}

View File

@@ -4,9 +4,11 @@ use crate::users::queries::GetUsersQuery;
#[tokio::test]
async fn returns_empty_when_no_users() {
let ctx = TestContextBuilder::new().build();
let b = TestContextBuilder::new();
let user = b.user_repo.clone();
let social_query = b.social_query.clone();
let result = get_users::execute(&ctx, GetUsersQuery).await.unwrap();
let result = get_users::execute(user, social_query, GetUsersQuery).await.unwrap();
assert!(result.users.is_empty());
assert!(result.remote_actors.is_empty());

View File

@@ -9,7 +9,7 @@ use uuid::Uuid;
use crate::{
auth::{commands::RegisterCommand, register},
test_helpers::TestContextBuilder,
users::{commands::UpdateProfileCommand, update_profile},
users::{commands::UpdateProfileCommand, deps::UpdateProfileDeps, update_profile},
};
async fn register_user(
@@ -40,15 +40,20 @@ async fn register_user(
async fn updates_display_name() {
let users = InMemoryUserRepository::new();
let events = NoopEventPublisher::new();
let ctx = TestContextBuilder::new()
let b = TestContextBuilder::new()
.with_users(Arc::clone(&users) as _)
.with_event_publisher(Arc::clone(&events) as _)
.build();
.with_event_publisher(Arc::clone(&events) as _);
let deps = UpdateProfileDeps {
user: b.user_repo.clone(),
object_storage: b.object_storage.clone(),
event_publisher: b.event_publisher.clone(),
};
let ctx = b.build();
let uid = register_user(&ctx, &users).await;
update_profile::execute(
&ctx,
&deps,
UpdateProfileCommand {
user_id: uid,
display_name: Some("Alice W.".into()),
@@ -74,14 +79,18 @@ async fn updates_display_name() {
#[tokio::test]
async fn rejects_invalid_avatar_content_type() {
let users = InMemoryUserRepository::new();
let ctx = TestContextBuilder::new()
.with_users(Arc::clone(&users) as _)
.build();
let b = TestContextBuilder::new().with_users(Arc::clone(&users) as _);
let deps = UpdateProfileDeps {
user: b.user_repo.clone(),
object_storage: b.object_storage.clone(),
event_publisher: b.event_publisher.clone(),
};
let ctx = b.build();
let uid = register_user(&ctx, &users).await;
let result = update_profile::execute(
&ctx,
&deps,
UpdateProfileCommand {
user_id: uid,
display_name: None,
@@ -102,15 +111,20 @@ async fn rejects_invalid_avatar_content_type() {
async fn uploads_avatar() {
let users = InMemoryUserRepository::new();
let events = NoopEventPublisher::new();
let ctx = TestContextBuilder::new()
let b = TestContextBuilder::new()
.with_users(Arc::clone(&users) as _)
.with_event_publisher(Arc::clone(&events) as _)
.build();
.with_event_publisher(Arc::clone(&events) as _);
let deps = UpdateProfileDeps {
user: b.user_repo.clone(),
object_storage: b.object_storage.clone(),
event_publisher: b.event_publisher.clone(),
};
let ctx = b.build();
let uid = register_user(&ctx, &users).await;
update_profile::execute(
&ctx,
&deps,
UpdateProfileCommand {
user_id: uid,
display_name: None,
@@ -142,15 +156,20 @@ async fn uploads_avatar() {
async fn uploads_banner() {
let users = InMemoryUserRepository::new();
let events = NoopEventPublisher::new();
let ctx = TestContextBuilder::new()
let b = TestContextBuilder::new()
.with_users(Arc::clone(&users) as _)
.with_event_publisher(Arc::clone(&events) as _)
.build();
.with_event_publisher(Arc::clone(&events) as _);
let deps = UpdateProfileDeps {
user: b.user_repo.clone(),
object_storage: b.object_storage.clone(),
event_publisher: b.event_publisher.clone(),
};
let ctx = b.build();
let uid = register_user(&ctx, &users).await;
update_profile::execute(
&ctx,
&deps,
UpdateProfileCommand {
user_id: uid,
display_name: None,
@@ -180,10 +199,16 @@ async fn uploads_banner() {
#[tokio::test]
async fn fails_for_nonexistent_user() {
let ctx = TestContextBuilder::new().build();
let b = TestContextBuilder::new();
let deps = UpdateProfileDeps {
user: b.user_repo.clone(),
object_storage: b.object_storage.clone(),
event_publisher: b.event_publisher.clone(),
};
let _ctx = b.build();
let result = update_profile::execute(
&ctx,
&deps,
UpdateProfileCommand {
user_id: Uuid::new_v4(),
display_name: Some("Ghost".into()),
@@ -203,14 +228,18 @@ async fn fails_for_nonexistent_user() {
#[tokio::test]
async fn rejects_invalid_banner_content_type() {
let users = InMemoryUserRepository::new();
let ctx = TestContextBuilder::new()
.with_users(Arc::clone(&users) as _)
.build();
let b = TestContextBuilder::new().with_users(Arc::clone(&users) as _);
let deps = UpdateProfileDeps {
user: b.user_repo.clone(),
object_storage: b.object_storage.clone(),
event_publisher: b.event_publisher.clone(),
};
let ctx = b.build();
let uid = register_user(&ctx, &users).await;
let result = update_profile::execute(
&ctx,
&deps,
UpdateProfileCommand {
user_id: uid,
display_name: None,
@@ -231,15 +260,20 @@ async fn rejects_invalid_banner_content_type() {
async fn text_only_update_emits_user_updated_no_image_stored() {
let users = InMemoryUserRepository::new();
let events = NoopEventPublisher::new();
let ctx = TestContextBuilder::new()
let b = TestContextBuilder::new()
.with_users(Arc::clone(&users) as _)
.with_event_publisher(Arc::clone(&events) as _)
.build();
.with_event_publisher(Arc::clone(&events) as _);
let deps = UpdateProfileDeps {
user: b.user_repo.clone(),
object_storage: b.object_storage.clone(),
event_publisher: b.event_publisher.clone(),
};
let ctx = b.build();
let uid = register_user(&ctx, &users).await;
update_profile::execute(
&ctx,
&deps,
UpdateProfileCommand {
user_id: uid,
display_name: Some("Alice Updated".into()),

View File

@@ -14,13 +14,15 @@ use crate::{
async fn saves_profile_fields() {
let fields_repo = InMemoryProfileFieldsRepo::new();
let events = NoopEventPublisher::new();
let ctx = TestContextBuilder::new()
let b = TestContextBuilder::new()
.with_profile_fields(Arc::clone(&fields_repo) as _)
.with_event_publisher(Arc::clone(&events) as _)
.build();
.with_event_publisher(Arc::clone(&events) as _);
let profile_fields = b.profile_fields_repo.clone();
let event_publisher = b.event_publisher.clone();
update_profile_fields::execute(
&ctx,
profile_fields,
event_publisher,
UpdateProfileFieldsCommand {
user_id: Uuid::nil(),
fields: vec![
@@ -48,7 +50,9 @@ async fn saves_profile_fields() {
#[tokio::test]
async fn rejects_more_than_four_fields() {
let ctx = TestContextBuilder::new().build();
let b = TestContextBuilder::new();
let profile_fields = b.profile_fields_repo.clone();
let event_publisher = b.event_publisher.clone();
let fields: Vec<ProfileField> = (0..5)
.map(|i| ProfileField {
@@ -58,7 +62,8 @@ async fn rejects_more_than_four_fields() {
.collect();
let result = update_profile_fields::execute(
&ctx,
profile_fields,
event_publisher,
UpdateProfileFieldsCommand {
user_id: Uuid::nil(),
fields,

View File

@@ -11,14 +11,14 @@ use crate::{
#[tokio::test]
async fn updates_federate_goals() {
let settings_repo = InMemoryUserSettingsRepository::new();
let ctx = TestContextBuilder::new()
.with_user_settings(Arc::clone(&settings_repo) as _)
.build();
let b = TestContextBuilder::new()
.with_user_settings(Arc::clone(&settings_repo) as _);
let user_settings = b.user_settings_repo.clone();
let uid = Uuid::nil();
crate::users::update_settings::execute(
&ctx,
user_settings.clone(),
UpdateUserSettingsCommand {
user_id: uid,
federate_goals: true,
@@ -27,6 +27,6 @@ async fn updates_federate_goals() {
.await
.unwrap();
let settings = get_settings::execute(&ctx, uid).await.unwrap();
let settings = get_settings::execute(user_settings, uid).await.unwrap();
assert!(settings.federate_goals());
}