test: shared factories and command builders
This commit is contained in:
@@ -1,15 +1,13 @@
|
||||
use crate::test_support::{login_command, register_command};
|
||||
use std::sync::Arc;
|
||||
|
||||
use domain::models::UserRole;
|
||||
use domain::testing::InMemoryUserRepository;
|
||||
|
||||
use crate::{
|
||||
auth::{
|
||||
commands::RegisterCommand,
|
||||
deps::{LoginDeps, RegisterDeps},
|
||||
login,
|
||||
queries::LoginCommand,
|
||||
register,
|
||||
login, register,
|
||||
},
|
||||
test_helpers::TestContextBuilder,
|
||||
};
|
||||
@@ -23,10 +21,8 @@ async fn setup_user(b: &TestContextBuilder, email: &str, password: &str) {
|
||||
register::execute(
|
||||
&deps,
|
||||
RegisterCommand {
|
||||
email: email.to_string(),
|
||||
username: "testuser".to_string(),
|
||||
password: password.to_string(),
|
||||
role: UserRole::Standard,
|
||||
..register_command(email, "testuser")
|
||||
},
|
||||
)
|
||||
.await
|
||||
@@ -46,15 +42,9 @@ async fn test_login_valid_credentials_returns_token() {
|
||||
refresh_session: b.refresh_session_repo.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
let result = login::execute(
|
||||
&deps,
|
||||
LoginCommand {
|
||||
email: "carol@example.com".into(),
|
||||
password: "secret123".into(),
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let result = login::execute(&deps, login_command("carol@example.com", "secret123"))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert!(!result.token.is_empty());
|
||||
assert!(!result.refresh_token.is_empty());
|
||||
@@ -74,14 +64,7 @@ async fn test_login_wrong_password_fails() {
|
||||
refresh_session: b.refresh_session_repo.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
let result = login::execute(
|
||||
&deps,
|
||||
LoginCommand {
|
||||
email: "dave@example.com".into(),
|
||||
password: "wrong_password".into(),
|
||||
},
|
||||
)
|
||||
.await;
|
||||
let result = login::execute(&deps, login_command("dave@example.com", "wrong_password")).await;
|
||||
|
||||
assert!(result.is_err());
|
||||
}
|
||||
@@ -96,14 +79,7 @@ async fn test_login_unknown_email_fails() {
|
||||
refresh_session: b.refresh_session_repo.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
let result = login::execute(
|
||||
&deps,
|
||||
LoginCommand {
|
||||
email: "nobody@example.com".into(),
|
||||
password: "anything".into(),
|
||||
},
|
||||
)
|
||||
.await;
|
||||
let result = login::execute(&deps, login_command("nobody@example.com", "anything")).await;
|
||||
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
use crate::test_support::{login_command, register_command};
|
||||
use std::sync::Arc;
|
||||
|
||||
use domain::models::UserRole;
|
||||
use domain::testing::InMemoryUserRepository;
|
||||
|
||||
use crate::{
|
||||
auth::{
|
||||
commands::RegisterCommand,
|
||||
deps::{LoginDeps, LogoutDeps, RefreshDeps, RegisterDeps},
|
||||
login, logout,
|
||||
queries::LoginCommand,
|
||||
refresh, register,
|
||||
login, logout, refresh, register,
|
||||
},
|
||||
test_helpers::TestContextBuilder,
|
||||
};
|
||||
@@ -24,17 +21,9 @@ async fn logout_revokes_refresh_token() {
|
||||
password_hasher: b.password_hasher.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
register::execute(
|
||||
®_deps,
|
||||
RegisterCommand {
|
||||
email: "bob@example.com".to_string(),
|
||||
username: "bob".to_string(),
|
||||
password: "password123".to_string(),
|
||||
role: UserRole::Standard,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
register::execute(®_deps, register_command("bob@example.com", "bob"))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let login_deps = LoginDeps {
|
||||
user: b.user_repo.clone(),
|
||||
@@ -43,15 +32,9 @@ async fn logout_revokes_refresh_token() {
|
||||
refresh_session: b.refresh_session_repo.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
let login_result = login::execute(
|
||||
&login_deps,
|
||||
LoginCommand {
|
||||
email: "bob@example.com".into(),
|
||||
password: "password123".into(),
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
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(),
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
use crate::test_support::{login_command, register_command};
|
||||
use std::sync::Arc;
|
||||
|
||||
use domain::models::UserRole;
|
||||
use domain::testing::InMemoryUserRepository;
|
||||
|
||||
use crate::{
|
||||
auth::{
|
||||
commands::RegisterCommand,
|
||||
deps::{LoginDeps, RefreshDeps, RegisterDeps},
|
||||
login,
|
||||
queries::LoginCommand,
|
||||
refresh, register,
|
||||
login, refresh, register,
|
||||
},
|
||||
test_helpers::TestContextBuilder,
|
||||
};
|
||||
@@ -20,17 +17,9 @@ async fn login_user(b: &TestContextBuilder) -> login::LoginResult {
|
||||
password_hasher: b.password_hasher.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
register::execute(
|
||||
®_deps,
|
||||
RegisterCommand {
|
||||
email: "alice@example.com".to_string(),
|
||||
username: "alice".to_string(),
|
||||
password: "password123".to_string(),
|
||||
role: UserRole::Standard,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
register::execute(®_deps, register_command("alice@example.com", "alice"))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let login_deps = LoginDeps {
|
||||
user: b.user_repo.clone(),
|
||||
@@ -41,10 +30,7 @@ async fn login_user(b: &TestContextBuilder) -> login::LoginResult {
|
||||
};
|
||||
login::execute(
|
||||
&login_deps,
|
||||
LoginCommand {
|
||||
email: "alice@example.com".into(),
|
||||
password: "password123".into(),
|
||||
},
|
||||
login_command("alice@example.com", "password123"),
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::test_support::register_command;
|
||||
use std::sync::Arc;
|
||||
|
||||
use domain::models::UserRole;
|
||||
use domain::ports::UserRepository;
|
||||
use domain::testing::InMemoryUserRepository;
|
||||
use domain::value_objects::Email;
|
||||
@@ -11,12 +11,7 @@ use crate::{
|
||||
};
|
||||
|
||||
fn cmd(email: &str) -> RegisterCommand {
|
||||
RegisterCommand {
|
||||
email: email.to_string(),
|
||||
username: "alice".to_string(),
|
||||
password: "password123".to_string(),
|
||||
role: UserRole::Standard,
|
||||
}
|
||||
register_command(email, "alice")
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -67,10 +62,8 @@ async fn test_register_short_password_fails() {
|
||||
let result = register::execute(
|
||||
&deps,
|
||||
RegisterCommand {
|
||||
email: "x@y.com".to_string(),
|
||||
username: "testuser".to_string(),
|
||||
password: "short".to_string(),
|
||||
role: UserRole::Standard,
|
||||
..register_command("x@y.com", "testuser")
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -1,43 +1,18 @@
|
||||
use domain::testing::{test_movie_with_year, test_review};
|
||||
use std::sync::Arc;
|
||||
|
||||
use chrono::Utc;
|
||||
|
||||
use domain::{
|
||||
models::{Movie, Review},
|
||||
ports::{MovieCommand, MovieQuery, ReviewRepository},
|
||||
testing::{
|
||||
FakeDiaryQuery, InMemoryMovieRepository, InMemoryReviewRepository, NoopEventPublisher,
|
||||
},
|
||||
value_objects::{MovieId, MovieTitle, Rating, ReleaseYear, UserId},
|
||||
value_objects::{MovieId, UserId},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
diary::commands::DeleteReviewCommand, diary::delete_review, diary::deps::DeleteReviewDeps,
|
||||
};
|
||||
|
||||
fn make_movie() -> Movie {
|
||||
Movie::new(
|
||||
None,
|
||||
MovieTitle::new("Terminator".into()).unwrap(),
|
||||
ReleaseYear::new(1984).unwrap(),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
fn make_review(movie_id: MovieId, user_id: UserId) -> Review {
|
||||
Review::new(
|
||||
movie_id,
|
||||
user_id,
|
||||
Rating::new(4).unwrap(),
|
||||
None,
|
||||
Utc::now().naive_utc(),
|
||||
None,
|
||||
false,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_review_removes_it() {
|
||||
let movies = InMemoryMovieRepository::new();
|
||||
@@ -45,9 +20,9 @@ async fn test_delete_review_removes_it() {
|
||||
let diary = FakeDiaryQuery::new();
|
||||
let events = NoopEventPublisher::new();
|
||||
|
||||
let movie = make_movie();
|
||||
let movie = test_movie_with_year("Terminator", 1984);
|
||||
let user_id = UserId::from_uuid(uuid::Uuid::new_v4());
|
||||
let review = make_review(movie.id().clone(), user_id.clone());
|
||||
let review = test_review(movie.id(), &user_id, 4);
|
||||
|
||||
movies.upsert_movie(&movie).await.unwrap();
|
||||
reviews.save_review(&review).await.unwrap();
|
||||
@@ -87,7 +62,7 @@ async fn test_delete_review_wrong_user_is_unauthorized() {
|
||||
let movie_id = MovieId::from_uuid(uuid::Uuid::new_v4());
|
||||
let owner_id = UserId::from_uuid(uuid::Uuid::new_v4());
|
||||
let other_id = uuid::Uuid::new_v4();
|
||||
let review = make_review(movie_id, owner_id);
|
||||
let review = test_review(&movie_id, &owner_id, 4);
|
||||
|
||||
reviews.save_review(&review).await.unwrap();
|
||||
|
||||
|
||||
@@ -1,30 +1,15 @@
|
||||
use crate::test_support::edit_review_command;
|
||||
use std::sync::Arc;
|
||||
|
||||
use chrono::Utc;
|
||||
use uuid::Uuid;
|
||||
|
||||
use domain::{
|
||||
models::Review,
|
||||
models::ReviewEdit,
|
||||
ports::ReviewRepository,
|
||||
testing::{InMemoryReviewRepository, NoopEventPublisher},
|
||||
value_objects::{Comment, MovieId, Rating, ReviewId, UserId, WatchMedium},
|
||||
testing::{InMemoryReviewRepository, NoopEventPublisher, test_review},
|
||||
value_objects::{Comment, MovieId, ReviewId, UserId, WatchMedium},
|
||||
};
|
||||
|
||||
use crate::diary::{commands::EditReviewCommand, deps::EditReviewDeps, edit_review};
|
||||
|
||||
fn make_review(user_id: UserId) -> Review {
|
||||
Review::new(
|
||||
MovieId::generate(),
|
||||
user_id,
|
||||
Rating::new(3).unwrap(),
|
||||
Some(Comment::new("original comment".into()).unwrap()),
|
||||
Utc::now().naive_utc(),
|
||||
Some(WatchMedium::Streaming),
|
||||
false,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
async fn setup() -> (
|
||||
Arc<InMemoryReviewRepository>,
|
||||
Arc<NoopEventPublisher>,
|
||||
@@ -34,7 +19,11 @@ async fn setup() -> (
|
||||
let reviews = InMemoryReviewRepository::new();
|
||||
let events = NoopEventPublisher::new();
|
||||
let user_id = UserId::generate();
|
||||
let review = make_review(user_id.clone());
|
||||
let review = test_review(&MovieId::generate(), &user_id, 3).apply_edit(ReviewEdit {
|
||||
comment: Some(Some(Comment::new("original comment".into()).unwrap())),
|
||||
watch_medium: Some(Some(WatchMedium::Streaming)),
|
||||
..Default::default()
|
||||
});
|
||||
let review_id = review.id().clone();
|
||||
reviews.save_review(&review).await.unwrap();
|
||||
(reviews, events, review_id, user_id)
|
||||
@@ -59,11 +48,7 @@ async fn edit_own_review_updates_rating() {
|
||||
EditReviewCommand {
|
||||
review_id: review_id.value(),
|
||||
requesting_user_id: user_id.value(),
|
||||
rating: Some(5),
|
||||
comment: None,
|
||||
watched_at: None,
|
||||
watch_medium: None,
|
||||
spoilers: None,
|
||||
..edit_review_command(5)
|
||||
},
|
||||
)
|
||||
.await
|
||||
@@ -80,20 +65,9 @@ async fn edit_nonexistent_review_returns_not_found() {
|
||||
let reviews = InMemoryReviewRepository::new();
|
||||
let events = NoopEventPublisher::new();
|
||||
|
||||
let err = edit_review::execute(
|
||||
&deps(&reviews, &events),
|
||||
EditReviewCommand {
|
||||
review_id: Uuid::new_v4(),
|
||||
requesting_user_id: Uuid::new_v4(),
|
||||
rating: Some(5),
|
||||
comment: None,
|
||||
watched_at: None,
|
||||
watch_medium: None,
|
||||
spoilers: None,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap_err();
|
||||
let err = edit_review::execute(&deps(&reviews, &events), edit_review_command(5))
|
||||
.await
|
||||
.unwrap_err();
|
||||
|
||||
assert!(matches!(err, domain::errors::DomainError::NotFound(_)));
|
||||
}
|
||||
@@ -106,12 +80,7 @@ async fn edit_other_users_review_returns_forbidden() {
|
||||
&deps(&reviews, &events),
|
||||
EditReviewCommand {
|
||||
review_id: review_id.value(),
|
||||
requesting_user_id: Uuid::new_v4(),
|
||||
rating: Some(5),
|
||||
comment: None,
|
||||
watched_at: None,
|
||||
watch_medium: None,
|
||||
spoilers: None,
|
||||
..edit_review_command(5)
|
||||
},
|
||||
)
|
||||
.await
|
||||
@@ -129,11 +98,7 @@ async fn edit_publishes_review_updated_event() {
|
||||
EditReviewCommand {
|
||||
review_id: review_id.value(),
|
||||
requesting_user_id: user_id.value(),
|
||||
rating: Some(1),
|
||||
comment: None,
|
||||
watched_at: None,
|
||||
watch_medium: None,
|
||||
spoilers: None,
|
||||
..edit_review_command(1)
|
||||
},
|
||||
)
|
||||
.await
|
||||
@@ -154,13 +119,11 @@ async fn edit_sets_watch_medium() {
|
||||
edit_review::execute(
|
||||
&deps(&reviews, &events),
|
||||
EditReviewCommand {
|
||||
rating: None,
|
||||
review_id: review_id.value(),
|
||||
requesting_user_id: user_id.value(),
|
||||
rating: None,
|
||||
comment: None,
|
||||
watched_at: None,
|
||||
watch_medium: Some(Some(WatchMedium::Cinema)),
|
||||
spoilers: None,
|
||||
..edit_review_command(1)
|
||||
},
|
||||
)
|
||||
.await
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
use domain::testing::test_movie_with_year;
|
||||
use std::sync::Arc;
|
||||
|
||||
use uuid::Uuid;
|
||||
|
||||
use domain::{
|
||||
models::Movie,
|
||||
ports::MovieCommand,
|
||||
testing::{FakeDiaryQuery, InMemoryMovieProfileRepository, InMemoryMovieRepository},
|
||||
value_objects::{MovieTitle, ReleaseYear},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@@ -39,13 +38,7 @@ async fn fails_when_movie_not_found() {
|
||||
async fn returns_movie_social_page() {
|
||||
let movies = InMemoryMovieRepository::new();
|
||||
|
||||
let movie = Movie::new(
|
||||
None,
|
||||
MovieTitle::new("Social Movie".into()).unwrap(),
|
||||
ReleaseYear::new(2024).unwrap(),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let movie = test_movie_with_year("Social Movie", 2024);
|
||||
let movie_uuid = movie.id().value();
|
||||
movies.upsert_movie(&movie).await.unwrap();
|
||||
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
use domain::testing::test_movie_with_year;
|
||||
use std::sync::Arc;
|
||||
|
||||
use domain::{
|
||||
models::Movie,
|
||||
ports::DiaryQuery,
|
||||
services::review_history::Trend,
|
||||
value_objects::{MovieTitle, ReleaseYear},
|
||||
};
|
||||
use domain::{ports::DiaryQuery, services::review_history::Trend};
|
||||
|
||||
use crate::{
|
||||
diary::deps::GetReviewHistoryDeps, diary::get_review_history,
|
||||
@@ -14,13 +10,7 @@ use crate::{
|
||||
|
||||
#[tokio::test]
|
||||
async fn returns_empty_history() {
|
||||
let movie = Movie::new(
|
||||
None,
|
||||
MovieTitle::new("Test".into()).unwrap(),
|
||||
ReleaseYear::new(2024).unwrap(),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let movie = test_movie_with_year("Test", 2024);
|
||||
let movie_id = movie.id().value();
|
||||
|
||||
let diary = domain::testing::FakeDiaryQuery::new();
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
use crate::test_support::register_command;
|
||||
use domain::testing::{test_movie_with_year, test_review};
|
||||
use std::sync::Arc;
|
||||
|
||||
use uuid::Uuid;
|
||||
|
||||
use domain::errors::DomainError;
|
||||
use domain::models::{DiaryEntry, Movie, Review, UserRole, collections::Paginated};
|
||||
use domain::models::{DiaryEntry, collections::Paginated};
|
||||
use domain::testing::FakeDiaryQuery;
|
||||
use domain::value_objects::{Email, MovieTitle, Rating, ReleaseYear, UserId};
|
||||
use domain::value_objects::{Email, UserId};
|
||||
|
||||
use crate::auth::commands::RegisterCommand;
|
||||
use crate::auth::deps::RegisterDeps;
|
||||
use crate::auth::register;
|
||||
use crate::diary::deps::GetUserFeedDeps;
|
||||
@@ -20,17 +21,9 @@ async fn setup_user(b: &TestContextBuilder, email: &str, username: &str) {
|
||||
password_hasher: b.password_hasher.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
register::execute(
|
||||
&deps,
|
||||
RegisterCommand {
|
||||
email: email.into(),
|
||||
username: username.into(),
|
||||
password: "password123".into(),
|
||||
role: UserRole::Standard,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
register::execute(&deps, register_command(email, username))
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -43,23 +36,8 @@ async fn user_feed_carries_author_and_entries() {
|
||||
let uid = user.id().value();
|
||||
|
||||
let diary = FakeDiaryQuery::new();
|
||||
let movie = Movie::new(
|
||||
None,
|
||||
MovieTitle::new("Feed Movie".into()).unwrap(),
|
||||
ReleaseYear::new(2020).unwrap(),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let review = Review::new(
|
||||
movie.id().clone(),
|
||||
UserId::from_uuid(uid),
|
||||
Rating::new(5).unwrap(),
|
||||
None,
|
||||
chrono::Utc::now().naive_utc(),
|
||||
None,
|
||||
false,
|
||||
)
|
||||
.unwrap();
|
||||
let movie = test_movie_with_year("Feed Movie", 2020);
|
||||
let review = test_review(movie.id(), &UserId::from_uuid(uid), 5);
|
||||
diary.set_diary_page(Paginated {
|
||||
items: vec![DiaryEntry::new(movie, review)],
|
||||
total_count: 1,
|
||||
|
||||
@@ -1,20 +1,14 @@
|
||||
use crate::test_support::{log_review_command, log_review_command_manual};
|
||||
use domain::testing::test_movie_with_year;
|
||||
use std::sync::Arc;
|
||||
|
||||
use chrono::Utc;
|
||||
|
||||
use domain::{
|
||||
models::Movie,
|
||||
ports::MovieCommand,
|
||||
value_objects::{MovieTitle, ReleaseYear},
|
||||
};
|
||||
use domain::ports::MovieCommand;
|
||||
|
||||
use domain::testing::{InMemoryMovieRepository, InMemoryReviewRepository, NoopEventPublisher};
|
||||
|
||||
use crate::{
|
||||
diary::commands::{LogReviewCommand, MovieInput},
|
||||
diary::log_review,
|
||||
diary::review_logger::DefaultReviewLogger,
|
||||
test_helpers::TestContextBuilder,
|
||||
diary::commands::LogReviewCommand, diary::log_review,
|
||||
diary::review_logger::DefaultReviewLogger, test_helpers::TestContextBuilder,
|
||||
};
|
||||
|
||||
fn build_logger(
|
||||
@@ -32,26 +26,6 @@ fn build_logger(
|
||||
))
|
||||
}
|
||||
|
||||
fn movie_input_manual(title: &str, year: u16) -> MovieInput {
|
||||
MovieInput {
|
||||
movie_id: None,
|
||||
external_metadata_id: None,
|
||||
manual_title: Some(title.to_string()),
|
||||
manual_release_year: Some(year),
|
||||
manual_director: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn movie_input_by_id(id: uuid::Uuid) -> MovieInput {
|
||||
MovieInput {
|
||||
movie_id: Some(id),
|
||||
external_metadata_id: None,
|
||||
manual_title: None,
|
||||
manual_release_year: None,
|
||||
manual_director: None,
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_log_review_creates_movie_and_review() {
|
||||
let movies = InMemoryMovieRepository::new();
|
||||
@@ -60,15 +34,7 @@ async fn test_log_review_creates_movie_and_review() {
|
||||
let logger = build_logger(&movies, &reviews, &events);
|
||||
|
||||
let user_id = uuid::Uuid::new_v4();
|
||||
let cmd = LogReviewCommand {
|
||||
user_id,
|
||||
input: movie_input_manual("Blade Runner", 1982),
|
||||
rating: 4,
|
||||
comment: None,
|
||||
watched_at: Utc::now().naive_utc(),
|
||||
watch_medium: None,
|
||||
spoilers: false,
|
||||
};
|
||||
let cmd = log_review_command_manual(user_id, "Blade Runner", 1982);
|
||||
|
||||
log_review::execute(&logger, cmd).await.unwrap();
|
||||
|
||||
@@ -81,13 +47,7 @@ async fn test_log_review_reuses_existing_movie() {
|
||||
let movies = InMemoryMovieRepository::new();
|
||||
let reviews = InMemoryReviewRepository::new();
|
||||
|
||||
let existing_movie = Movie::new(
|
||||
None,
|
||||
MovieTitle::new("Alien".into()).unwrap(),
|
||||
ReleaseYear::new(1979).unwrap(),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let existing_movie = test_movie_with_year("Alien", 1979);
|
||||
let movie_uuid = existing_movie.id().value();
|
||||
movies.upsert_movie(&existing_movie).await.unwrap();
|
||||
|
||||
@@ -95,13 +55,8 @@ async fn test_log_review_reuses_existing_movie() {
|
||||
let logger = build_logger(&movies, &reviews, &events);
|
||||
|
||||
let cmd = LogReviewCommand {
|
||||
user_id: uuid::Uuid::new_v4(),
|
||||
input: movie_input_by_id(movie_uuid),
|
||||
rating: 5,
|
||||
comment: None,
|
||||
watched_at: Utc::now().naive_utc(),
|
||||
watch_medium: None,
|
||||
spoilers: false,
|
||||
..log_review_command(uuid::Uuid::new_v4(), movie_uuid)
|
||||
};
|
||||
|
||||
log_review::execute(&logger, cmd).await.unwrap();
|
||||
@@ -118,13 +73,8 @@ async fn test_log_review_with_invalid_rating_fails() {
|
||||
let logger = build_logger(&movies, &reviews, &events);
|
||||
|
||||
let cmd = LogReviewCommand {
|
||||
user_id: uuid::Uuid::new_v4(),
|
||||
input: movie_input_manual("Some Film", 2000),
|
||||
rating: 6,
|
||||
comment: None,
|
||||
watched_at: Utc::now().naive_utc(),
|
||||
watch_medium: None,
|
||||
spoilers: false,
|
||||
..log_review_command_manual(uuid::Uuid::new_v4(), "Some Film", 2000)
|
||||
};
|
||||
let result = log_review::execute(&logger, cmd).await;
|
||||
assert!(result.is_err(), "rating > 5 should fail");
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use super::*;
|
||||
use crate::diary::commands::MovieInput;
|
||||
use domain::testing::test_movie_with_year;
|
||||
use domain::{
|
||||
errors::DomainError,
|
||||
models::{MetadataSearchCriteria, Movie},
|
||||
@@ -17,16 +18,6 @@ fn make_input(ext_id: Option<&str>, title: Option<&str>, year: Option<u16>) -> M
|
||||
}
|
||||
}
|
||||
|
||||
fn make_movie() -> Movie {
|
||||
Movie::new(
|
||||
None,
|
||||
MovieTitle::new("Inception".to_string()).unwrap(),
|
||||
ReleaseYear::new(2010).unwrap(),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
struct RepoWithExternalMovie(Movie);
|
||||
struct RepoEmpty;
|
||||
struct RepoWithTitleMatch(Movie);
|
||||
@@ -213,7 +204,7 @@ fn external_id_strategy_cannot_handle_cmd_without_id() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn external_id_strategy_returns_cached_movie() {
|
||||
let movie = make_movie();
|
||||
let movie = test_movie_with_year("Inception", 2010);
|
||||
let repo = RepoWithExternalMovie(movie.clone());
|
||||
let meta = MetaErrors;
|
||||
let deps = MovieResolverDeps {
|
||||
@@ -227,7 +218,7 @@ async fn external_id_strategy_returns_cached_movie() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn external_id_strategy_fetches_from_metadata_when_not_cached() {
|
||||
let movie = make_movie();
|
||||
let movie = test_movie_with_year("Inception", 2010);
|
||||
let repo = RepoEmpty;
|
||||
let meta = MetaReturnsMovie(movie);
|
||||
let deps = MovieResolverDeps {
|
||||
@@ -268,7 +259,7 @@ fn title_strategy_cannot_handle_cmd_without_title() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn title_strategy_fetches_from_metadata() {
|
||||
let movie = make_movie();
|
||||
let movie = test_movie_with_year("Inception", 2010);
|
||||
let repo = RepoEmpty;
|
||||
let meta = MetaReturnsMovie(movie);
|
||||
let deps = MovieResolverDeps {
|
||||
@@ -309,7 +300,7 @@ fn manual_strategy_cannot_handle_cmd_without_title() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn manual_strategy_returns_existing_movie() {
|
||||
let movie = make_movie();
|
||||
let movie = test_movie_with_year("Inception", 2010);
|
||||
let repo = RepoWithTitleMatch(movie.clone());
|
||||
let meta = MetaErrors;
|
||||
let deps = MovieResolverDeps {
|
||||
@@ -365,7 +356,7 @@ async fn resolver_returns_error_when_no_strategy_matches() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn resolver_uses_cached_movie_when_external_id_matches() {
|
||||
let movie = make_movie();
|
||||
let movie = test_movie_with_year("Inception", 2010);
|
||||
let repo = RepoWithExternalMovie(movie.clone());
|
||||
let meta = MetaErrors;
|
||||
let deps = MovieResolverDeps {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use crate::test_support::{log_review_command, log_review_command_manual};
|
||||
use domain::testing::{test_movie_with_external_id, test_movie_with_year};
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use chrono::Utc;
|
||||
use domain::{
|
||||
errors::DomainError,
|
||||
models::WatchlistEntry,
|
||||
@@ -11,11 +12,11 @@ use domain::{
|
||||
FakeMetadataClient, InMemoryMovieRepository, InMemoryReviewRepository,
|
||||
InMemoryWatchlistRepository, NoopEventPublisher,
|
||||
},
|
||||
value_objects::{ExternalMetadataId, MovieId, MovieTitle, PosterUrl, ReleaseYear, UserId},
|
||||
value_objects::{ExternalMetadataId, MovieId, PosterUrl, UserId},
|
||||
};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::diary::commands::{LogReviewCommand, MovieInput};
|
||||
use crate::diary::commands::LogReviewCommand;
|
||||
use crate::diary::review_logger::DefaultReviewLogger;
|
||||
use crate::ports::ReviewLogger;
|
||||
|
||||
@@ -44,21 +45,7 @@ async fn logs_review_with_manual_movie() {
|
||||
let logger = make_logger(&movies, &reviews, &watchlist, &events);
|
||||
|
||||
let uid = Uuid::new_v4();
|
||||
let cmd = LogReviewCommand {
|
||||
user_id: uid,
|
||||
input: MovieInput {
|
||||
movie_id: None,
|
||||
external_metadata_id: None,
|
||||
manual_title: Some("Test Film".into()),
|
||||
manual_release_year: Some(2024),
|
||||
manual_director: None,
|
||||
},
|
||||
rating: 4,
|
||||
comment: None,
|
||||
watched_at: Utc::now().naive_utc(),
|
||||
watch_medium: None,
|
||||
spoilers: false,
|
||||
};
|
||||
let cmd = log_review_command_manual(uid, "Test Film", 2024);
|
||||
|
||||
logger.log_review(cmd).await.unwrap();
|
||||
|
||||
@@ -78,13 +65,7 @@ async fn removes_from_watchlist_on_review() {
|
||||
let user_id = UserId::from_uuid(uid);
|
||||
|
||||
// Create and store movie
|
||||
let movie = Movie::new(
|
||||
None,
|
||||
MovieTitle::new("Watchlisted Film".into()).unwrap(),
|
||||
ReleaseYear::new(2024).unwrap(),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let movie = test_movie_with_year("Watchlisted Film", 2024);
|
||||
let movie_id = movie.id().value();
|
||||
movies.upsert_movie(&movie).await.unwrap();
|
||||
|
||||
@@ -95,19 +76,8 @@ async fn removes_from_watchlist_on_review() {
|
||||
|
||||
// Log review for same movie
|
||||
let cmd = LogReviewCommand {
|
||||
user_id: uid,
|
||||
input: MovieInput {
|
||||
movie_id: Some(movie_id),
|
||||
external_metadata_id: None,
|
||||
manual_title: None,
|
||||
manual_release_year: None,
|
||||
manual_director: None,
|
||||
},
|
||||
rating: 5,
|
||||
comment: None,
|
||||
watched_at: Utc::now().naive_utc(),
|
||||
watch_medium: None,
|
||||
spoilers: false,
|
||||
..log_review_command(uid, movie_id)
|
||||
};
|
||||
|
||||
logger.log_review(cmd).await.unwrap();
|
||||
@@ -123,30 +93,13 @@ async fn logs_review_with_existing_movie_by_id() {
|
||||
let events = NoopEventPublisher::new();
|
||||
let logger = make_logger(&movies, &reviews, &watchlist, &events);
|
||||
|
||||
let movie = Movie::new(
|
||||
None,
|
||||
MovieTitle::new("Existing Film".into()).unwrap(),
|
||||
ReleaseYear::new(2020).unwrap(),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let movie = test_movie_with_year("Existing Film", 2020);
|
||||
let movie_uuid = movie.id().value();
|
||||
movies.upsert_movie(&movie).await.unwrap();
|
||||
|
||||
let cmd = LogReviewCommand {
|
||||
user_id: Uuid::new_v4(),
|
||||
input: MovieInput {
|
||||
movie_id: Some(movie_uuid),
|
||||
external_metadata_id: None,
|
||||
manual_title: None,
|
||||
manual_release_year: None,
|
||||
manual_director: None,
|
||||
},
|
||||
rating: 3,
|
||||
comment: None,
|
||||
watched_at: Utc::now().naive_utc(),
|
||||
watch_medium: None,
|
||||
spoilers: false,
|
||||
..log_review_command(Uuid::new_v4(), movie_uuid)
|
||||
};
|
||||
|
||||
logger.log_review(cmd).await.unwrap();
|
||||
@@ -163,21 +116,7 @@ async fn existing_movie_not_found_returns_error() {
|
||||
let events = NoopEventPublisher::new();
|
||||
let logger = make_logger(&movies, &reviews, &watchlist, &events);
|
||||
|
||||
let cmd = LogReviewCommand {
|
||||
user_id: Uuid::new_v4(),
|
||||
input: MovieInput {
|
||||
movie_id: Some(Uuid::new_v4()),
|
||||
external_metadata_id: None,
|
||||
manual_title: None,
|
||||
manual_release_year: None,
|
||||
manual_director: None,
|
||||
},
|
||||
rating: 4,
|
||||
comment: None,
|
||||
watched_at: Utc::now().naive_utc(),
|
||||
watch_medium: None,
|
||||
spoilers: false,
|
||||
};
|
||||
let cmd = log_review_command(Uuid::new_v4(), Uuid::new_v4());
|
||||
|
||||
assert!(logger.log_review(cmd).await.is_err());
|
||||
}
|
||||
@@ -191,19 +130,8 @@ async fn invalid_rating_returns_error() {
|
||||
let logger = make_logger(&movies, &reviews, &watchlist, &events);
|
||||
|
||||
let cmd = LogReviewCommand {
|
||||
user_id: Uuid::new_v4(),
|
||||
input: MovieInput {
|
||||
movie_id: None,
|
||||
external_metadata_id: None,
|
||||
manual_title: Some("Film".into()),
|
||||
manual_release_year: Some(2024),
|
||||
manual_director: None,
|
||||
},
|
||||
rating: 6,
|
||||
comment: None,
|
||||
watched_at: Utc::now().naive_utc(),
|
||||
watch_medium: None,
|
||||
spoilers: false,
|
||||
..log_review_command_manual(Uuid::new_v4(), "Film", 2024)
|
||||
};
|
||||
|
||||
let result = logger.log_review(cmd).await;
|
||||
@@ -221,21 +149,7 @@ async fn watchlist_not_present_does_not_publish_removed() {
|
||||
let events = NoopEventPublisher::new();
|
||||
let logger = make_logger(&movies, &reviews, &watchlist, &events);
|
||||
|
||||
let cmd = LogReviewCommand {
|
||||
user_id: Uuid::new_v4(),
|
||||
input: MovieInput {
|
||||
movie_id: None,
|
||||
external_metadata_id: None,
|
||||
manual_title: Some("No Watchlist Film".into()),
|
||||
manual_release_year: Some(2024),
|
||||
manual_director: None,
|
||||
},
|
||||
rating: 4,
|
||||
comment: None,
|
||||
watched_at: Utc::now().naive_utc(),
|
||||
watch_medium: None,
|
||||
spoilers: false,
|
||||
};
|
||||
let cmd = log_review_command_manual(Uuid::new_v4(), "No Watchlist Film", 2024);
|
||||
|
||||
logger.log_review(cmd).await.unwrap();
|
||||
|
||||
@@ -256,12 +170,10 @@ impl MetadataClient for MetadataClientWithExternalId {
|
||||
&self,
|
||||
_criteria: &MetadataSearchCriteria,
|
||||
) -> Result<Movie, DomainError> {
|
||||
Ok(Movie::new(
|
||||
Some(ExternalMetadataId::new("tmdb:99999".into()).unwrap()),
|
||||
MovieTitle::new("Discovered Film".into()).unwrap(),
|
||||
ReleaseYear::new(2024).unwrap(),
|
||||
None,
|
||||
None,
|
||||
Ok(test_movie_with_external_id(
|
||||
"Discovered Film",
|
||||
2024,
|
||||
ExternalMetadataId::new("tmdb:99999".into()).unwrap(),
|
||||
))
|
||||
}
|
||||
|
||||
@@ -290,19 +202,8 @@ async fn publishes_movie_discovered_for_new_movie_with_external_id() {
|
||||
);
|
||||
|
||||
let cmd = LogReviewCommand {
|
||||
user_id: Uuid::new_v4(),
|
||||
input: MovieInput {
|
||||
movie_id: None,
|
||||
external_metadata_id: None,
|
||||
manual_title: Some("Discovered Film".into()),
|
||||
manual_release_year: Some(2024),
|
||||
manual_director: None,
|
||||
},
|
||||
rating: 5,
|
||||
comment: None,
|
||||
watched_at: Utc::now().naive_utc(),
|
||||
watch_medium: None,
|
||||
spoilers: false,
|
||||
..log_review_command_manual(Uuid::new_v4(), "Discovered Film", 2024)
|
||||
};
|
||||
|
||||
logger.log_review(cmd).await.unwrap();
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
use crate::test_support::create_goal_command;
|
||||
use std::sync::Arc;
|
||||
|
||||
use domain::events::DomainEvent;
|
||||
use domain::testing::{FakeStatsRepository, InMemoryGoalRepository, NoopEventPublisher};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::goals::create;
|
||||
use crate::goals::deps::GoalCommandDeps;
|
||||
use crate::goals::{commands::CreateGoalCommand, create};
|
||||
use crate::test_helpers::TestContextBuilder;
|
||||
|
||||
#[tokio::test]
|
||||
@@ -20,16 +21,9 @@ async fn creates_goal_and_returns_progress() {
|
||||
event_publisher: Arc::clone(&events) as _,
|
||||
};
|
||||
|
||||
let result = create::execute(
|
||||
&deps,
|
||||
CreateGoalCommand {
|
||||
user_id: Uuid::nil(),
|
||||
year: 2025,
|
||||
target_count: 50,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let result = create::execute(&deps, create_goal_command(2025, 50))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(result.goal.year(), 2025);
|
||||
assert_eq!(result.goal.target_count(), 50);
|
||||
@@ -50,16 +44,9 @@ async fn creates_goal_with_review_count() {
|
||||
event_publisher: Arc::clone(&events) as _,
|
||||
};
|
||||
|
||||
let result = create::execute(
|
||||
&deps,
|
||||
CreateGoalCommand {
|
||||
user_id: Uuid::nil(),
|
||||
year: 2025,
|
||||
target_count: 50,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let result = create::execute(&deps, create_goal_command(2025, 50))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(result.current_count, 5);
|
||||
assert_eq!(goals.count(), 1);
|
||||
@@ -76,16 +63,9 @@ async fn emits_goal_created_event() {
|
||||
event_publisher: Arc::clone(&events) as _,
|
||||
};
|
||||
|
||||
create::execute(
|
||||
&deps,
|
||||
CreateGoalCommand {
|
||||
user_id: Uuid::nil(),
|
||||
year: 2025,
|
||||
target_count: 10,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
create::execute(&deps, create_goal_command(2025, 10))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let published = events.published();
|
||||
assert!(
|
||||
@@ -104,23 +84,11 @@ async fn rejects_duplicate_year() {
|
||||
stats: b.stats_repo.clone(),
|
||||
event_publisher: b.event_publisher.clone(),
|
||||
};
|
||||
let cmd = CreateGoalCommand {
|
||||
user_id: Uuid::nil(),
|
||||
year: 2025,
|
||||
target_count: 10,
|
||||
};
|
||||
let cmd = create_goal_command(2025, 10);
|
||||
|
||||
create::execute(&deps, cmd).await.unwrap();
|
||||
|
||||
let result = create::execute(
|
||||
&deps,
|
||||
CreateGoalCommand {
|
||||
user_id: Uuid::nil(),
|
||||
year: 2025,
|
||||
target_count: 20,
|
||||
},
|
||||
)
|
||||
.await;
|
||||
let result = create::execute(&deps, create_goal_command(2025, 20)).await;
|
||||
|
||||
assert!(result.is_err());
|
||||
}
|
||||
@@ -134,15 +102,7 @@ async fn rejects_year_before_2020() {
|
||||
stats: b.stats_repo.clone(),
|
||||
event_publisher: b.event_publisher.clone(),
|
||||
};
|
||||
let result = create::execute(
|
||||
&deps,
|
||||
CreateGoalCommand {
|
||||
user_id: Uuid::nil(),
|
||||
year: 2019,
|
||||
target_count: 10,
|
||||
},
|
||||
)
|
||||
.await;
|
||||
let result = create::execute(&deps, create_goal_command(2019, 10)).await;
|
||||
|
||||
assert!(result.is_err());
|
||||
}
|
||||
@@ -156,15 +116,7 @@ async fn rejects_zero_target() {
|
||||
stats: b.stats_repo.clone(),
|
||||
event_publisher: b.event_publisher.clone(),
|
||||
};
|
||||
let result = create::execute(
|
||||
&deps,
|
||||
CreateGoalCommand {
|
||||
user_id: Uuid::nil(),
|
||||
year: 2025,
|
||||
target_count: 0,
|
||||
},
|
||||
)
|
||||
.await;
|
||||
let result = create::execute(&deps, create_goal_command(2025, 0)).await;
|
||||
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
use crate::test_support::create_goal_command;
|
||||
use std::sync::Arc;
|
||||
|
||||
use domain::testing::{FakeStatsRepository, InMemoryGoalRepository, NoopEventPublisher};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::goals::deps::GoalCommandDeps;
|
||||
use crate::goals::{
|
||||
commands::{CreateGoalCommand, DeleteGoalCommand},
|
||||
create, delete,
|
||||
};
|
||||
use crate::goals::{commands::DeleteGoalCommand, create, delete};
|
||||
use crate::test_helpers::TestContextBuilder;
|
||||
|
||||
#[tokio::test]
|
||||
@@ -22,16 +20,9 @@ async fn deletes_existing_goal() {
|
||||
event_publisher: Arc::clone(&events) as _,
|
||||
};
|
||||
|
||||
create::execute(
|
||||
&deps,
|
||||
CreateGoalCommand {
|
||||
user_id: Uuid::nil(),
|
||||
year: 2025,
|
||||
target_count: 10,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
create::execute(&deps, create_goal_command(2025, 10))
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(goals.count(), 1);
|
||||
|
||||
delete::execute(
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use crate::test_support::create_goal_command;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::goals::deps::{GoalCommandDeps, GoalQueryDeps};
|
||||
use crate::goals::{commands::CreateGoalCommand, create, get, queries::GetGoalQuery};
|
||||
use crate::goals::{create, get, queries::GetGoalQuery};
|
||||
use crate::test_helpers::TestContextBuilder;
|
||||
|
||||
#[tokio::test]
|
||||
@@ -18,16 +19,9 @@ async fn returns_goal_when_exists() {
|
||||
stats: b.stats_repo.clone(),
|
||||
};
|
||||
|
||||
create::execute(
|
||||
&cmd_deps,
|
||||
CreateGoalCommand {
|
||||
user_id: Uuid::nil(),
|
||||
year: 2025,
|
||||
target_count: 50,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
create::execute(&cmd_deps, create_goal_command(2025, 50))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let result = get::execute(
|
||||
&query_deps,
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use crate::test_support::create_goal_command;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::goals::deps::{GoalCommandDeps, GoalQueryDeps};
|
||||
use crate::goals::{commands::CreateGoalCommand, create, list, queries::ListGoalsQuery};
|
||||
use crate::goals::{create, list, queries::ListGoalsQuery};
|
||||
use crate::test_helpers::TestContextBuilder;
|
||||
|
||||
#[tokio::test]
|
||||
@@ -38,16 +39,9 @@ async fn returns_all_goals_for_user() {
|
||||
};
|
||||
|
||||
for year in [2023, 2024, 2025] {
|
||||
create::execute(
|
||||
&cmd_deps,
|
||||
CreateGoalCommand {
|
||||
user_id: Uuid::nil(),
|
||||
year,
|
||||
target_count: 10,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
create::execute(&cmd_deps, create_goal_command(year, 10))
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
let result = list::execute(
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
use uuid::Uuid;
|
||||
use crate::test_support::{create_goal_command, update_goal_command};
|
||||
|
||||
use crate::goals::deps::GoalCommandDeps;
|
||||
use crate::goals::{
|
||||
commands::{CreateGoalCommand, UpdateGoalCommand},
|
||||
create, update,
|
||||
};
|
||||
use crate::goals::{create, update};
|
||||
use crate::test_helpers::TestContextBuilder;
|
||||
|
||||
#[tokio::test]
|
||||
@@ -17,27 +14,13 @@ async fn updates_target_count() {
|
||||
event_publisher: b.event_publisher.clone(),
|
||||
};
|
||||
|
||||
create::execute(
|
||||
&deps,
|
||||
CreateGoalCommand {
|
||||
user_id: Uuid::nil(),
|
||||
year: 2025,
|
||||
target_count: 10,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
create::execute(&deps, create_goal_command(2025, 10))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let result = update::execute(
|
||||
&deps,
|
||||
UpdateGoalCommand {
|
||||
user_id: Uuid::nil(),
|
||||
year: 2025,
|
||||
target_count: 100,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let result = update::execute(&deps, update_goal_command(2025, 100))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(result.goal.target_count(), 100);
|
||||
}
|
||||
@@ -51,15 +34,7 @@ async fn fails_when_goal_not_found() {
|
||||
stats: b.stats_repo.clone(),
|
||||
event_publisher: b.event_publisher.clone(),
|
||||
};
|
||||
let result = update::execute(
|
||||
&deps,
|
||||
UpdateGoalCommand {
|
||||
user_id: Uuid::nil(),
|
||||
year: 2025,
|
||||
target_count: 10,
|
||||
},
|
||||
)
|
||||
.await;
|
||||
let result = update::execute(&deps, update_goal_command(2025, 10)).await;
|
||||
|
||||
assert!(result.is_err());
|
||||
}
|
||||
@@ -74,26 +49,11 @@ async fn rejects_zero_target() {
|
||||
event_publisher: b.event_publisher.clone(),
|
||||
};
|
||||
|
||||
create::execute(
|
||||
&deps,
|
||||
CreateGoalCommand {
|
||||
user_id: Uuid::nil(),
|
||||
year: 2025,
|
||||
target_count: 10,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
create::execute(&deps, create_goal_command(2025, 10))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let result = update::execute(
|
||||
&deps,
|
||||
UpdateGoalCommand {
|
||||
user_id: Uuid::nil(),
|
||||
year: 2025,
|
||||
target_count: 0,
|
||||
},
|
||||
)
|
||||
.await;
|
||||
let result = update::execute(&deps, update_goal_command(2025, 0)).await;
|
||||
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
@@ -1,23 +1,21 @@
|
||||
use crate::test_support::{apply_import_mapping_command, create_import_session_command};
|
||||
use domain::testing::{test_movie_with_external_id, test_movie_with_year};
|
||||
use std::sync::Arc;
|
||||
|
||||
use uuid::Uuid;
|
||||
|
||||
use domain::{
|
||||
models::{
|
||||
AnnotatedRow, Movie,
|
||||
AnnotatedRow,
|
||||
import::{ImportRow, ParsedFile, RowResult},
|
||||
},
|
||||
ports::{DocumentParser, MovieCommand},
|
||||
testing::{InMemoryImportSessionRepository, InMemoryMovieRepository},
|
||||
value_objects::{ExternalMetadataId, MovieTitle, ReleaseYear},
|
||||
value_objects::ExternalMetadataId,
|
||||
};
|
||||
|
||||
use crate::import::deps::{ApplyMappingDeps, CreateSessionDeps};
|
||||
use crate::import::{
|
||||
apply_mapping,
|
||||
commands::{ApplyImportMappingCommand, CreateImportSessionCommand},
|
||||
create_session,
|
||||
};
|
||||
use crate::import::{apply_mapping, create_session};
|
||||
use crate::test_helpers::TestContextBuilder;
|
||||
|
||||
#[tokio::test]
|
||||
@@ -33,11 +31,7 @@ async fn applies_mapping_to_session() {
|
||||
|
||||
let session = create_session::execute(
|
||||
&create_deps,
|
||||
CreateImportSessionCommand {
|
||||
user_id,
|
||||
bytes: b"title\nTest".to_vec(),
|
||||
format: domain::models::FileFormat::Csv,
|
||||
},
|
||||
create_import_session_command(user_id, b"title\nTest"),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
@@ -50,11 +44,7 @@ async fn applies_mapping_to_session() {
|
||||
|
||||
let rows = apply_mapping::execute(
|
||||
&mapping_deps,
|
||||
ApplyImportMappingCommand {
|
||||
user_id,
|
||||
session_id: session.session_id.value(),
|
||||
mappings: vec![],
|
||||
},
|
||||
apply_import_mapping_command(user_id, session.session_id.value()),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
@@ -75,11 +65,7 @@ async fn fails_when_session_not_found() {
|
||||
|
||||
let result = apply_mapping::execute(
|
||||
&deps,
|
||||
ApplyImportMappingCommand {
|
||||
user_id: Uuid::new_v4(),
|
||||
session_id: Uuid::new_v4(),
|
||||
mappings: vec![],
|
||||
},
|
||||
apply_import_mapping_command(Uuid::new_v4(), Uuid::new_v4()),
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -123,13 +109,7 @@ async fn marks_duplicate_by_external_id() {
|
||||
let sessions = InMemoryImportSessionRepository::new();
|
||||
|
||||
let ext_id = ExternalMetadataId::new("tt1234567".into()).unwrap();
|
||||
let movie = Movie::new(
|
||||
Some(ext_id),
|
||||
MovieTitle::new("Known Movie".into()).unwrap(),
|
||||
ReleaseYear::new(2020).unwrap(),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let movie = test_movie_with_external_id("Known Movie", 2020, ext_id);
|
||||
movies.upsert_movie(&movie).await.unwrap();
|
||||
|
||||
let parser = Arc::new(DuplicateTestParser {
|
||||
@@ -150,11 +130,7 @@ async fn marks_duplicate_by_external_id() {
|
||||
|
||||
let session = create_session::execute(
|
||||
&create_deps,
|
||||
CreateImportSessionCommand {
|
||||
user_id,
|
||||
bytes: b"title\nKnown Movie".to_vec(),
|
||||
format: domain::models::FileFormat::Csv,
|
||||
},
|
||||
create_import_session_command(user_id, b"title\nKnown Movie"),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
@@ -167,11 +143,7 @@ async fn marks_duplicate_by_external_id() {
|
||||
|
||||
let rows = apply_mapping::execute(
|
||||
&mapping_deps,
|
||||
ApplyImportMappingCommand {
|
||||
user_id,
|
||||
session_id: session.session_id.value(),
|
||||
mappings: vec![],
|
||||
},
|
||||
apply_import_mapping_command(user_id, session.session_id.value()),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
@@ -185,13 +157,7 @@ async fn marks_duplicate_by_title_and_year() {
|
||||
let movies = InMemoryMovieRepository::new();
|
||||
let sessions = InMemoryImportSessionRepository::new();
|
||||
|
||||
let movie = Movie::new(
|
||||
None,
|
||||
MovieTitle::new("Duplicate Film".into()).unwrap(),
|
||||
ReleaseYear::new(2022).unwrap(),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let movie = test_movie_with_year("Duplicate Film", 2022);
|
||||
movies.upsert_movie(&movie).await.unwrap();
|
||||
|
||||
let parser = Arc::new(DuplicateTestParser {
|
||||
@@ -211,11 +177,7 @@ async fn marks_duplicate_by_title_and_year() {
|
||||
|
||||
let session = create_session::execute(
|
||||
&create_deps,
|
||||
CreateImportSessionCommand {
|
||||
user_id,
|
||||
bytes: b"title\nDuplicate Film".to_vec(),
|
||||
format: domain::models::FileFormat::Csv,
|
||||
},
|
||||
create_import_session_command(user_id, b"title\nDuplicate Film"),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
@@ -228,11 +190,7 @@ async fn marks_duplicate_by_title_and_year() {
|
||||
|
||||
let rows = apply_mapping::execute(
|
||||
&mapping_deps,
|
||||
ApplyImportMappingCommand {
|
||||
user_id,
|
||||
session_id: session.session_id.value(),
|
||||
mappings: vec![],
|
||||
},
|
||||
apply_import_mapping_command(user_id, session.session_id.value()),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::test_support::apply_import_profile_command;
|
||||
use std::sync::Arc;
|
||||
|
||||
use chrono::Utc;
|
||||
@@ -7,8 +8,8 @@ use domain::testing::{InMemoryImportProfileRepository, InMemoryImportSessionRepo
|
||||
use domain::value_objects::{ImportProfileId, UserId};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::import::apply_profile;
|
||||
use crate::import::deps::ApplyProfileDeps;
|
||||
use crate::import::{apply_profile, commands::ApplyImportProfileCommand};
|
||||
|
||||
#[tokio::test]
|
||||
async fn fails_when_profile_not_found() {
|
||||
@@ -22,11 +23,7 @@ async fn fails_when_profile_not_found() {
|
||||
|
||||
let result = apply_profile::execute(
|
||||
&deps,
|
||||
ApplyImportProfileCommand {
|
||||
user_id: Uuid::new_v4(),
|
||||
session_id: Uuid::new_v4(),
|
||||
profile_id: Uuid::new_v4(),
|
||||
},
|
||||
apply_import_profile_command(Uuid::new_v4(), Uuid::new_v4(), Uuid::new_v4()),
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -56,11 +53,7 @@ async fn fails_when_session_not_found() {
|
||||
|
||||
let result = apply_profile::execute(
|
||||
&deps,
|
||||
ApplyImportProfileCommand {
|
||||
user_id,
|
||||
session_id: Uuid::new_v4(),
|
||||
profile_id: profile_id.value(),
|
||||
},
|
||||
apply_import_profile_command(user_id, Uuid::new_v4(), profile_id.value()),
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -98,11 +91,7 @@ async fn applies_profile_mappings_to_session() {
|
||||
|
||||
apply_profile::execute(
|
||||
&deps,
|
||||
ApplyImportProfileCommand {
|
||||
user_id,
|
||||
session_id: session_id.value(),
|
||||
profile_id: profile_id.value(),
|
||||
},
|
||||
apply_import_profile_command(user_id, session_id.value(), profile_id.value()),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
use crate::test_support::create_import_session_command;
|
||||
use std::sync::Arc;
|
||||
|
||||
use chrono::Utc;
|
||||
use uuid::Uuid;
|
||||
|
||||
use domain::models::import::{DomainField, Transform};
|
||||
use domain::models::{FieldMapping, FileFormat, ImportProfile};
|
||||
use domain::models::{FieldMapping, ImportProfile};
|
||||
use domain::ports::{ImportProfileRepository, ImportSessionRepository};
|
||||
use domain::testing::{InMemoryImportProfileRepository, InMemoryImportSessionRepository};
|
||||
use domain::value_objects::{ImportProfileId, UserId};
|
||||
|
||||
use crate::import::deps::{ApplyProfileAndMapDeps, CreateSessionDeps};
|
||||
use crate::import::{
|
||||
apply_profile_and_map, commands::ApplyProfileAndMapCommand,
|
||||
commands::CreateImportSessionCommand, create_session,
|
||||
};
|
||||
use crate::import::{apply_profile_and_map, commands::ApplyProfileAndMapCommand, create_session};
|
||||
use crate::test_helpers::TestContextBuilder;
|
||||
|
||||
#[tokio::test]
|
||||
@@ -69,11 +67,7 @@ async fn applies_profile_then_regenerates_mapping() {
|
||||
};
|
||||
let created = create_session::execute(
|
||||
&create_deps,
|
||||
CreateImportSessionCommand {
|
||||
user_id,
|
||||
bytes: b"title\nTest".to_vec(),
|
||||
format: FileFormat::Csv,
|
||||
},
|
||||
create_import_session_command(user_id, b"title\nTest"),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
use crate::test_support::create_import_session_command;
|
||||
use std::sync::Arc;
|
||||
|
||||
use uuid::Uuid;
|
||||
|
||||
use domain::testing::InMemoryImportSessionRepository;
|
||||
|
||||
use crate::import::create_session;
|
||||
use crate::import::deps::CreateSessionDeps;
|
||||
use crate::import::{commands::CreateImportSessionCommand, create_session};
|
||||
use crate::test_helpers::TestContextBuilder;
|
||||
|
||||
#[tokio::test]
|
||||
@@ -20,11 +21,7 @@ async fn creates_session_with_parsed_file() {
|
||||
|
||||
let result = create_session::execute(
|
||||
&deps,
|
||||
CreateImportSessionCommand {
|
||||
user_id: Uuid::new_v4(),
|
||||
bytes: b"col1\nval1".to_vec(),
|
||||
format: domain::models::FileFormat::Csv,
|
||||
},
|
||||
create_import_session_command(Uuid::new_v4(), b"col1\nval1"),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::test_support::execute_import_command;
|
||||
use std::sync::Arc;
|
||||
|
||||
use domain::models::{AnnotatedRow, ImportSession, import::RowResult};
|
||||
@@ -59,9 +60,8 @@ async fn imports_confirmed_rows() {
|
||||
let result = execute::execute(
|
||||
&deps,
|
||||
ExecuteImportCommand {
|
||||
user_id: uid,
|
||||
session_id: sid.value(),
|
||||
confirmed_indices: vec![0, 1],
|
||||
..execute_import_command(uid, sid.value())
|
||||
},
|
||||
)
|
||||
.await
|
||||
@@ -86,16 +86,9 @@ async fn skips_unconfirmed_rows() {
|
||||
review_logger: Arc::new(NoopReviewLogger),
|
||||
};
|
||||
|
||||
let result = execute::execute(
|
||||
&deps,
|
||||
ExecuteImportCommand {
|
||||
user_id: uid,
|
||||
session_id: sid.value(),
|
||||
confirmed_indices: vec![0],
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let result = execute::execute(&deps, execute_import_command(uid, sid.value()))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(result.imported, 1);
|
||||
assert_eq!(result.skipped_duplicates, 1);
|
||||
@@ -113,9 +106,8 @@ async fn fails_when_session_not_found() {
|
||||
let result = execute::execute(
|
||||
&deps,
|
||||
ExecuteImportCommand {
|
||||
user_id: Uuid::new_v4(),
|
||||
session_id: Uuid::new_v4(),
|
||||
confirmed_indices: vec![],
|
||||
..execute_import_command(Uuid::new_v4(), Uuid::new_v4())
|
||||
},
|
||||
)
|
||||
.await;
|
||||
@@ -149,16 +141,9 @@ async fn handles_datetime_format() {
|
||||
review_logger: Arc::new(NoopReviewLogger),
|
||||
};
|
||||
|
||||
let result = execute::execute(
|
||||
&deps,
|
||||
ExecuteImportCommand {
|
||||
user_id: uid,
|
||||
session_id: sid.value(),
|
||||
confirmed_indices: vec![0],
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let result = execute::execute(&deps, execute_import_command(uid, sid.value()))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(result.imported, 1);
|
||||
assert!(result.failed.is_empty());
|
||||
@@ -190,16 +175,9 @@ async fn fails_on_invalid_rating() {
|
||||
review_logger: Arc::new(NoopReviewLogger),
|
||||
};
|
||||
|
||||
let result = execute::execute(
|
||||
&deps,
|
||||
ExecuteImportCommand {
|
||||
user_id: uid,
|
||||
session_id: sid.value(),
|
||||
confirmed_indices: vec![0],
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let result = execute::execute(&deps, execute_import_command(uid, sid.value()))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(result.imported, 0);
|
||||
assert_eq!(result.failed.len(), 1);
|
||||
@@ -231,16 +209,9 @@ async fn fails_on_missing_watched_at() {
|
||||
review_logger: Arc::new(NoopReviewLogger),
|
||||
};
|
||||
|
||||
let result = execute::execute(
|
||||
&deps,
|
||||
ExecuteImportCommand {
|
||||
user_id: uid,
|
||||
session_id: sid.value(),
|
||||
confirmed_indices: vec![0],
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let result = execute::execute(&deps, execute_import_command(uid, sid.value()))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(result.imported, 0);
|
||||
assert_eq!(result.failed.len(), 1);
|
||||
@@ -272,16 +243,9 @@ async fn imports_row_with_external_metadata_id() {
|
||||
review_logger: Arc::new(NoopReviewLogger),
|
||||
};
|
||||
|
||||
let result = execute::execute(
|
||||
&deps,
|
||||
ExecuteImportCommand {
|
||||
user_id: uid,
|
||||
session_id: sid.value(),
|
||||
confirmed_indices: vec![0],
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let result = execute::execute(&deps, execute_import_command(uid, sid.value()))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(result.imported, 1);
|
||||
assert!(result.failed.is_empty());
|
||||
@@ -313,16 +277,9 @@ async fn imports_row_with_director_and_comment() {
|
||||
review_logger: Arc::new(NoopReviewLogger),
|
||||
};
|
||||
|
||||
let result = execute::execute(
|
||||
&deps,
|
||||
ExecuteImportCommand {
|
||||
user_id: uid,
|
||||
session_id: sid.value(),
|
||||
confirmed_indices: vec![0],
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let result = execute::execute(&deps, execute_import_command(uid, sid.value()))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(result.imported, 1);
|
||||
assert!(result.failed.is_empty());
|
||||
@@ -354,16 +311,9 @@ async fn handles_space_separated_datetime_format() {
|
||||
review_logger: Arc::new(NoopReviewLogger),
|
||||
};
|
||||
|
||||
let result = execute::execute(
|
||||
&deps,
|
||||
ExecuteImportCommand {
|
||||
user_id: uid,
|
||||
session_id: sid.value(),
|
||||
confirmed_indices: vec![0],
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let result = execute::execute(&deps, execute_import_command(uid, sid.value()))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(result.imported, 1);
|
||||
assert!(result.failed.is_empty());
|
||||
@@ -390,16 +340,9 @@ async fn reports_invalid_row_result_errors() {
|
||||
review_logger: Arc::new(NoopReviewLogger),
|
||||
};
|
||||
|
||||
let result = execute::execute(
|
||||
&deps,
|
||||
ExecuteImportCommand {
|
||||
user_id: uid,
|
||||
session_id: sid.value(),
|
||||
confirmed_indices: vec![0],
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let result = execute::execute(&deps, execute_import_command(uid, sid.value()))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(result.imported, 0);
|
||||
assert_eq!(result.failed.len(), 1);
|
||||
@@ -433,16 +376,9 @@ async fn fails_on_missing_rating() {
|
||||
review_logger: Arc::new(NoopReviewLogger),
|
||||
};
|
||||
|
||||
let result = execute::execute(
|
||||
&deps,
|
||||
ExecuteImportCommand {
|
||||
user_id: uid,
|
||||
session_id: sid.value(),
|
||||
confirmed_indices: vec![0],
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let result = execute::execute(&deps, execute_import_command(uid, sid.value()))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(result.imported, 0);
|
||||
assert_eq!(result.failed.len(), 1);
|
||||
@@ -475,16 +411,9 @@ async fn fails_on_unparseable_date() {
|
||||
review_logger: Arc::new(NoopReviewLogger),
|
||||
};
|
||||
|
||||
let result = execute::execute(
|
||||
&deps,
|
||||
ExecuteImportCommand {
|
||||
user_id: uid,
|
||||
session_id: sid.value(),
|
||||
confirmed_indices: vec![0],
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let result = execute::execute(&deps, execute_import_command(uid, sid.value()))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(result.imported, 0);
|
||||
assert_eq!(result.failed.len(), 1);
|
||||
@@ -517,16 +446,9 @@ async fn imports_row_without_release_year() {
|
||||
review_logger: Arc::new(NoopReviewLogger),
|
||||
};
|
||||
|
||||
let result = execute::execute(
|
||||
&deps,
|
||||
ExecuteImportCommand {
|
||||
user_id: uid,
|
||||
session_id: sid.value(),
|
||||
confirmed_indices: vec![0],
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
let result = execute::execute(&deps, execute_import_command(uid, sid.value()))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(result.imported, 1);
|
||||
assert!(result.failed.is_empty());
|
||||
@@ -547,16 +469,9 @@ async fn deletes_session_after_import() {
|
||||
review_logger: Arc::new(NoopReviewLogger),
|
||||
};
|
||||
|
||||
execute::execute(
|
||||
&deps,
|
||||
ExecuteImportCommand {
|
||||
user_id: uid,
|
||||
session_id: sid.value(),
|
||||
confirmed_indices: vec![0],
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
execute::execute(&deps, execute_import_command(uid, sid.value()))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
sessions.count(),
|
||||
@@ -599,9 +514,8 @@ async fn imports_more_rows_than_concurrency_limit() {
|
||||
let result = execute::execute(
|
||||
&deps,
|
||||
ExecuteImportCommand {
|
||||
user_id: uid,
|
||||
session_id: sid.value(),
|
||||
confirmed_indices,
|
||||
..execute_import_command(uid, sid.value())
|
||||
},
|
||||
)
|
||||
.await
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::test_support::confirm_watch_events_command;
|
||||
use std::sync::Arc;
|
||||
|
||||
use domain::models::{WatchEvent, WatchEventSource};
|
||||
@@ -45,14 +46,7 @@ async fn confirms_watch_event_via_review_logger() {
|
||||
|
||||
let result = confirm::execute(
|
||||
&deps(&watch_events, noop_logger()),
|
||||
ConfirmWatchEventsCommand {
|
||||
user_id: uid,
|
||||
confirmations: vec![WatchEventConfirmation {
|
||||
watch_event_id: event_id,
|
||||
rating: 4,
|
||||
comment: None,
|
||||
}],
|
||||
},
|
||||
confirm_watch_events_command(uid, event_id, 4),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
@@ -131,14 +125,7 @@ async fn rejects_other_users_event() {
|
||||
|
||||
let result = confirm::execute(
|
||||
&deps(&watch_events, noop_logger()),
|
||||
ConfirmWatchEventsCommand {
|
||||
user_id: intruder,
|
||||
confirmations: vec![WatchEventConfirmation {
|
||||
watch_event_id: event_id,
|
||||
rating: 3,
|
||||
comment: None,
|
||||
}],
|
||||
},
|
||||
confirm_watch_events_command(intruder, event_id, 3),
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -151,14 +138,7 @@ async fn fails_when_event_not_found() {
|
||||
|
||||
let result = confirm::execute(
|
||||
&deps(&watch_events, noop_logger()),
|
||||
ConfirmWatchEventsCommand {
|
||||
user_id: Uuid::new_v4(),
|
||||
confirmations: vec![WatchEventConfirmation {
|
||||
watch_event_id: Uuid::new_v4(),
|
||||
rating: 4,
|
||||
comment: None,
|
||||
}],
|
||||
},
|
||||
confirm_watch_events_command(Uuid::new_v4(), Uuid::new_v4(), 4),
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -211,14 +191,7 @@ async fn confirms_event_with_movie_id() {
|
||||
|
||||
let result = confirm::execute(
|
||||
&deps(&watch_events, review_logger),
|
||||
ConfirmWatchEventsCommand {
|
||||
user_id: uid,
|
||||
confirmations: vec![WatchEventConfirmation {
|
||||
watch_event_id: event_id,
|
||||
rating: 4,
|
||||
comment: None,
|
||||
}],
|
||||
},
|
||||
confirm_watch_events_command(uid, event_id, 4),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
@@ -293,7 +266,6 @@ async fn confirms_multiple_events() {
|
||||
let result = confirm::execute(
|
||||
&deps(&watch_events, noop_logger()),
|
||||
ConfirmWatchEventsCommand {
|
||||
user_id: uid,
|
||||
confirmations: vec![
|
||||
WatchEventConfirmation {
|
||||
watch_event_id: id1,
|
||||
@@ -306,6 +278,7 @@ async fn confirms_multiple_events() {
|
||||
comment: None,
|
||||
},
|
||||
],
|
||||
..confirm_watch_events_command(uid, id1, 3)
|
||||
},
|
||||
)
|
||||
.await
|
||||
@@ -333,14 +306,7 @@ async fn confirms_event_without_year() {
|
||||
|
||||
let result = confirm::execute(
|
||||
&deps(&watch_events, noop_logger()),
|
||||
ConfirmWatchEventsCommand {
|
||||
user_id: uid,
|
||||
confirmations: vec![WatchEventConfirmation {
|
||||
watch_event_id: event_id,
|
||||
rating: 3,
|
||||
comment: None,
|
||||
}],
|
||||
},
|
||||
confirm_watch_events_command(uid, event_id, 3),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::test_support::dismiss_watch_events_command;
|
||||
use std::sync::Arc;
|
||||
|
||||
use domain::models::{WatchEvent, WatchEventSource};
|
||||
@@ -7,7 +8,7 @@ use domain::value_objects::UserId;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::integrations::deps::DismissWatchEventsDeps;
|
||||
use crate::integrations::{commands::DismissWatchEventsCommand, dismiss};
|
||||
use crate::integrations::dismiss;
|
||||
|
||||
fn deps(watch_events: &Arc<InMemoryWatchEventRepository>) -> DismissWatchEventsDeps {
|
||||
DismissWatchEventsDeps {
|
||||
@@ -22,10 +23,7 @@ async fn dismisses_empty_list_returns_zero() {
|
||||
|
||||
let result = dismiss::execute(
|
||||
&deps(&events),
|
||||
DismissWatchEventsCommand {
|
||||
user_id: Uuid::new_v4(),
|
||||
event_ids: vec![],
|
||||
},
|
||||
dismiss_watch_events_command(Uuid::new_v4(), vec![]),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
@@ -39,10 +37,7 @@ async fn fails_when_event_not_found() {
|
||||
|
||||
let result = dismiss::execute(
|
||||
&deps(&events),
|
||||
DismissWatchEventsCommand {
|
||||
user_id: Uuid::new_v4(),
|
||||
event_ids: vec![Uuid::new_v4()],
|
||||
},
|
||||
dismiss_watch_events_command(Uuid::new_v4(), vec![Uuid::new_v4()]),
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -80,10 +75,7 @@ async fn dismisses_existing_events() {
|
||||
|
||||
let result = dismiss::execute(
|
||||
&deps(&watch_events),
|
||||
DismissWatchEventsCommand {
|
||||
user_id: uid,
|
||||
event_ids: vec![id1, id2],
|
||||
},
|
||||
dismiss_watch_events_command(uid, vec![id1, id2]),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
use crate::test_support::generate_webhook_token_command;
|
||||
use std::sync::Arc;
|
||||
|
||||
use domain::models::WatchEventSource;
|
||||
use domain::ports::WebhookTokenRepository;
|
||||
use domain::testing::InMemoryWebhookTokenRepository;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::integrations::deps::GenerateWebhookTokenDeps;
|
||||
use crate::integrations::{commands::GenerateWebhookTokenCommand, generate_token};
|
||||
use crate::integrations::generate_token;
|
||||
|
||||
#[tokio::test]
|
||||
async fn generates_token_and_saves() {
|
||||
@@ -17,11 +17,7 @@ async fn generates_token_and_saves() {
|
||||
&GenerateWebhookTokenDeps {
|
||||
webhook_token: Arc::clone(&tokens),
|
||||
},
|
||||
GenerateWebhookTokenCommand {
|
||||
user_id,
|
||||
provider: WatchEventSource::Jellyfin,
|
||||
label: None,
|
||||
},
|
||||
generate_webhook_token_command(user_id),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::test_support::generate_webhook_token_command;
|
||||
use std::sync::Arc;
|
||||
|
||||
use domain::models::WatchEventSource;
|
||||
@@ -47,11 +48,7 @@ async fn returns_tokens_after_generate() {
|
||||
|
||||
generate_token::execute(
|
||||
&generate_deps(&tokens),
|
||||
GenerateWebhookTokenCommand {
|
||||
user_id,
|
||||
provider: WatchEventSource::Jellyfin,
|
||||
label: None,
|
||||
},
|
||||
generate_webhook_token_command(user_id),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
@@ -59,9 +56,9 @@ async fn returns_tokens_after_generate() {
|
||||
generate_token::execute(
|
||||
&generate_deps(&tokens),
|
||||
GenerateWebhookTokenCommand {
|
||||
user_id,
|
||||
provider: WatchEventSource::Plex,
|
||||
label: Some("living room".into()),
|
||||
..generate_webhook_token_command(user_id)
|
||||
},
|
||||
)
|
||||
.await
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::test_support::generate_webhook_token_command;
|
||||
use std::sync::Arc;
|
||||
|
||||
use domain::models::WatchEventSource;
|
||||
@@ -7,7 +8,7 @@ use domain::testing::{
|
||||
};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::integrations::commands::{GenerateWebhookTokenCommand, IngestWatchEventCommand};
|
||||
use crate::integrations::commands::IngestWatchEventCommand;
|
||||
use crate::integrations::deps::{GenerateWebhookTokenDeps, IngestWatchEventDeps};
|
||||
use crate::integrations::{generate_token, ingest};
|
||||
|
||||
@@ -38,11 +39,7 @@ async fn ingests_watch_event() {
|
||||
&GenerateWebhookTokenDeps {
|
||||
webhook_token: Arc::clone(&tokens),
|
||||
},
|
||||
GenerateWebhookTokenCommand {
|
||||
user_id,
|
||||
provider: WatchEventSource::Jellyfin,
|
||||
label: None,
|
||||
},
|
||||
generate_webhook_token_command(user_id),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::test_support::generate_webhook_token_command;
|
||||
use std::sync::Arc;
|
||||
|
||||
use domain::models::WatchEventSource;
|
||||
use domain::ports::WebhookTokenRepository;
|
||||
use domain::testing::InMemoryWebhookTokenRepository;
|
||||
use uuid::Uuid;
|
||||
@@ -9,10 +9,8 @@ use crate::integrations::deps::{
|
||||
GenerateWebhookTokenDeps, GetWebhookTokensDeps, RevokeWebhookTokenDeps,
|
||||
};
|
||||
use crate::integrations::{
|
||||
commands::{GenerateWebhookTokenCommand, RevokeWebhookTokenCommand},
|
||||
generate_token, get_tokens,
|
||||
queries::GetWebhookTokensQuery,
|
||||
revoke_token,
|
||||
commands::RevokeWebhookTokenCommand, generate_token, get_tokens,
|
||||
queries::GetWebhookTokensQuery, revoke_token,
|
||||
};
|
||||
|
||||
#[tokio::test]
|
||||
@@ -25,11 +23,7 @@ async fn revokes_existing_token() {
|
||||
&GenerateWebhookTokenDeps {
|
||||
webhook_token: Arc::clone(&tokens),
|
||||
},
|
||||
GenerateWebhookTokenCommand {
|
||||
user_id,
|
||||
provider: WatchEventSource::Jellyfin,
|
||||
label: None,
|
||||
},
|
||||
generate_webhook_token_command(user_id),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@@ -22,6 +22,9 @@ pub mod wrapup;
|
||||
#[cfg(test)]
|
||||
pub mod test_helpers;
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_support;
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "tests/services.rs"]
|
||||
mod services_tests;
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
use domain::testing::test_movie_with_year;
|
||||
use std::sync::Arc;
|
||||
|
||||
use chrono::Utc;
|
||||
use domain::{
|
||||
models::{Movie, MovieProfile},
|
||||
models::MovieProfile,
|
||||
ports::MovieCommand,
|
||||
testing::{
|
||||
FakeSearchCommand, InMemoryMovieProfileRepository, InMemoryMovieRepository,
|
||||
PanicPersonCommand,
|
||||
},
|
||||
value_objects::{MovieId, MovieTitle, ReleaseYear},
|
||||
value_objects::MovieId,
|
||||
};
|
||||
|
||||
use crate::movies::{commands::EnrichMovieCommand, deps::EnrichMovieDeps, enrich_movie};
|
||||
@@ -19,13 +20,7 @@ async fn stores_profile_and_indexes() {
|
||||
let profile_repo = InMemoryMovieProfileRepository::new();
|
||||
// PanicPersonCommand is safe here — empty cast/crew means upsert_batch is never called
|
||||
|
||||
let movie = Movie::new(
|
||||
None,
|
||||
MovieTitle::new("Test".into()).unwrap(),
|
||||
ReleaseYear::new(2024).unwrap(),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let movie = test_movie_with_year("Test", 2024);
|
||||
let movie_id = MovieId::from_uuid(movie.id().value());
|
||||
movie_repo.upsert_movie(&movie).await.unwrap();
|
||||
|
||||
@@ -99,13 +94,7 @@ async fn extracts_and_indexes_persons() {
|
||||
let movie_repo = InMemoryMovieRepository::new();
|
||||
let profile_repo = InMemoryMovieProfileRepository::new();
|
||||
|
||||
let movie = Movie::new(
|
||||
None,
|
||||
MovieTitle::new("Cast Movie".into()).unwrap(),
|
||||
ReleaseYear::new(2024).unwrap(),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let movie = test_movie_with_year("Cast Movie", 2024);
|
||||
let movie_id = MovieId::from_uuid(movie.id().value());
|
||||
movie_repo.upsert_movie(&movie).await.unwrap();
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use crate::test_support::sync_poster_command;
|
||||
use domain::testing::{test_movie_with_external_id, test_movie_with_year};
|
||||
use std::sync::Arc;
|
||||
|
||||
use uuid::Uuid;
|
||||
@@ -10,13 +12,10 @@ use domain::{
|
||||
FakeSearchCommand, InMemoryMovieProfileRepository, InMemoryMovieRepository,
|
||||
NoopEventPublisher, NoopObjectStorage,
|
||||
},
|
||||
value_objects::{ExternalMetadataId, MovieTitle, PosterUrl, ReleaseYear},
|
||||
value_objects::{ExternalMetadataId, PosterUrl},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
diary::commands::SyncPosterCommand,
|
||||
movies::{deps::SyncPosterDeps, sync_poster},
|
||||
};
|
||||
use crate::movies::{deps::SyncPosterDeps, sync_poster};
|
||||
|
||||
fn default_deps() -> SyncPosterDeps {
|
||||
SyncPosterDeps {
|
||||
@@ -35,13 +34,7 @@ fn default_deps() -> SyncPosterDeps {
|
||||
async fn fails_when_movie_not_found() {
|
||||
let deps = default_deps();
|
||||
|
||||
let result = sync_poster::execute(
|
||||
&deps,
|
||||
SyncPosterCommand {
|
||||
movie_id: Uuid::new_v4(),
|
||||
},
|
||||
)
|
||||
.await;
|
||||
let result = sync_poster::execute(&deps, sync_poster_command(Uuid::new_v4())).await;
|
||||
|
||||
assert!(result.is_err());
|
||||
}
|
||||
@@ -49,13 +42,7 @@ async fn fails_when_movie_not_found() {
|
||||
#[tokio::test]
|
||||
async fn fails_when_no_external_id() {
|
||||
let movies = InMemoryMovieRepository::new();
|
||||
let movie = Movie::new(
|
||||
None,
|
||||
MovieTitle::new("Test".into()).unwrap(),
|
||||
ReleaseYear::new(2024).unwrap(),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let movie = test_movie_with_year("Test", 2024);
|
||||
let movie_id = movie.id().value();
|
||||
movies.upsert_movie(&movie).await.unwrap();
|
||||
|
||||
@@ -65,7 +52,7 @@ async fn fails_when_no_external_id() {
|
||||
..default_deps()
|
||||
};
|
||||
|
||||
let result = sync_poster::execute(&deps, SyncPosterCommand { movie_id }).await;
|
||||
let result = sync_poster::execute(&deps, sync_poster_command(movie_id)).await;
|
||||
|
||||
assert!(result.is_err());
|
||||
}
|
||||
@@ -94,13 +81,7 @@ impl MetadataClient for FakeMetaWithPoster {
|
||||
async fn syncs_poster_for_movie_with_external_id() {
|
||||
let movies = InMemoryMovieRepository::new();
|
||||
let ext_id = ExternalMetadataId::new("tmdb:999".into()).unwrap();
|
||||
let movie = Movie::new(
|
||||
Some(ext_id),
|
||||
MovieTitle::new("Poster Movie".into()).unwrap(),
|
||||
ReleaseYear::new(2024).unwrap(),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let movie = test_movie_with_external_id("Poster Movie", 2024, ext_id);
|
||||
let movie_id = movie.id().value();
|
||||
movies.upsert_movie(&movie).await.unwrap();
|
||||
|
||||
@@ -111,7 +92,7 @@ async fn syncs_poster_for_movie_with_external_id() {
|
||||
..default_deps()
|
||||
};
|
||||
|
||||
sync_poster::execute(&deps, SyncPosterCommand { movie_id })
|
||||
sync_poster::execute(&deps, sync_poster_command(movie_id))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
use domain::testing::test_user;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use domain::{
|
||||
errors::DomainError,
|
||||
models::{User, UserRole},
|
||||
ports::{
|
||||
BlockQuery, FollowCommand, FollowGraphQuery, FollowQuery, SocialCommand, UserRepository,
|
||||
},
|
||||
testing::InMemoryUserRepository,
|
||||
value_objects::{
|
||||
Email, FollowRelation, FollowStatus, FollowTarget, InstanceIdentity, PasswordHash,
|
||||
SocialActor, SocialIdentity, UserId, Username,
|
||||
FollowRelation, FollowStatus, FollowTarget, InstanceIdentity, SocialActor, SocialIdentity,
|
||||
UserId,
|
||||
},
|
||||
};
|
||||
use uuid::Uuid;
|
||||
@@ -247,12 +247,7 @@ fn instance() -> InstanceIdentity {
|
||||
}
|
||||
|
||||
async fn register_user(repo: &Arc<InMemoryUserRepository>, username: &str) -> UserId {
|
||||
let user = User::new(
|
||||
Email::new(format!("{username}@example.com")).unwrap(),
|
||||
Username::new(username.to_string()).unwrap(),
|
||||
PasswordHash::new("hashed-password".to_string()).unwrap(),
|
||||
UserRole::Standard,
|
||||
);
|
||||
let user = test_user(username);
|
||||
let id = user.id().clone();
|
||||
repo.save(&user).await.unwrap();
|
||||
id
|
||||
|
||||
240
crates/application/src/test_support.rs
Normal file
240
crates/application/src/test_support.rs
Normal file
@@ -0,0 +1,240 @@
|
||||
//! Command builders for tests. Each builder returns a command with sensible
|
||||
//! defaults; tests override individual fields with struct-update syntax:
|
||||
//! `LogReviewCommand { rating: 6, ..log_review_command(user, movie) }`.
|
||||
//! Moves to `tests/support/mod.rs` when application tests become integration tests.
|
||||
|
||||
use chrono::{NaiveDate, NaiveDateTime};
|
||||
use uuid::Uuid;
|
||||
|
||||
use domain::models::{FileFormat, UserRole, WatchEventSource};
|
||||
|
||||
use crate::auth::commands::RegisterCommand;
|
||||
use crate::auth::queries::LoginCommand;
|
||||
use crate::diary::commands::{EditReviewCommand, LogReviewCommand, MovieInput, SyncPosterCommand};
|
||||
use crate::goals::commands::{CreateGoalCommand, UpdateGoalCommand};
|
||||
use crate::import::commands::{
|
||||
ApplyImportMappingCommand, ApplyImportProfileCommand, CreateImportSessionCommand,
|
||||
ExecuteImportCommand,
|
||||
};
|
||||
use crate::integrations::commands::{
|
||||
ConfirmWatchEventsCommand, DismissWatchEventsCommand, GenerateWebhookTokenCommand,
|
||||
WatchEventConfirmation,
|
||||
};
|
||||
use crate::users::commands::UpdateProfileCommand;
|
||||
use crate::users::update_settings::UpdateUserSettingsCommand;
|
||||
use crate::watchlist::commands::AddToWatchlistCommand;
|
||||
use crate::wrapup::commands::RequestWrapUpCommand;
|
||||
|
||||
fn watched_at() -> NaiveDateTime {
|
||||
NaiveDate::from_ymd_opt(2024, 6, 15)
|
||||
.unwrap()
|
||||
.and_hms_opt(20, 0, 0)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub(crate) fn movie_input_by_id(movie_id: Uuid) -> MovieInput {
|
||||
MovieInput {
|
||||
movie_id: Some(movie_id),
|
||||
external_metadata_id: None,
|
||||
manual_title: None,
|
||||
manual_release_year: None,
|
||||
manual_director: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn movie_input_manual(title: &str, year: u16) -> MovieInput {
|
||||
MovieInput {
|
||||
movie_id: None,
|
||||
external_metadata_id: None,
|
||||
manual_title: Some(title.to_string()),
|
||||
manual_release_year: Some(year),
|
||||
manual_director: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn log_review_command(user_id: Uuid, movie_id: Uuid) -> LogReviewCommand {
|
||||
LogReviewCommand {
|
||||
user_id,
|
||||
input: movie_input_by_id(movie_id),
|
||||
rating: 4,
|
||||
comment: None,
|
||||
watched_at: watched_at(),
|
||||
watch_medium: None,
|
||||
spoilers: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn log_review_command_manual(user_id: Uuid, title: &str, year: u16) -> LogReviewCommand {
|
||||
LogReviewCommand {
|
||||
input: movie_input_manual(title, year),
|
||||
..log_review_command(user_id, Uuid::nil())
|
||||
}
|
||||
}
|
||||
|
||||
/// Edits only the rating; `review_id` and `requesting_user_id` are random.
|
||||
pub(crate) fn edit_review_command(rating: u8) -> EditReviewCommand {
|
||||
EditReviewCommand {
|
||||
review_id: Uuid::new_v4(),
|
||||
requesting_user_id: Uuid::new_v4(),
|
||||
rating: Some(rating),
|
||||
comment: None,
|
||||
watched_at: None,
|
||||
watch_medium: None,
|
||||
spoilers: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn sync_poster_command(movie_id: Uuid) -> SyncPosterCommand {
|
||||
SyncPosterCommand { movie_id }
|
||||
}
|
||||
|
||||
pub(crate) fn register_command(
|
||||
email: impl Into<String>,
|
||||
username: impl Into<String>,
|
||||
) -> RegisterCommand {
|
||||
RegisterCommand {
|
||||
email: email.into(),
|
||||
username: username.into(),
|
||||
password: "password123".to_string(),
|
||||
role: UserRole::Standard,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn login_command(email: impl Into<String>, password: impl Into<String>) -> LoginCommand {
|
||||
LoginCommand {
|
||||
email: email.into(),
|
||||
password: password.into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn create_goal_command(year: u16, target_count: u32) -> CreateGoalCommand {
|
||||
CreateGoalCommand {
|
||||
user_id: Uuid::nil(),
|
||||
year,
|
||||
target_count,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn update_goal_command(year: u16, target_count: u32) -> UpdateGoalCommand {
|
||||
UpdateGoalCommand {
|
||||
user_id: Uuid::nil(),
|
||||
year,
|
||||
target_count,
|
||||
}
|
||||
}
|
||||
|
||||
/// Confirms indices `[0]`.
|
||||
pub(crate) fn execute_import_command(user_id: Uuid, session_id: Uuid) -> ExecuteImportCommand {
|
||||
ExecuteImportCommand {
|
||||
user_id,
|
||||
session_id,
|
||||
confirmed_indices: vec![0],
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn create_import_session_command(
|
||||
user_id: Uuid,
|
||||
csv: &[u8],
|
||||
) -> CreateImportSessionCommand {
|
||||
CreateImportSessionCommand {
|
||||
user_id,
|
||||
bytes: csv.to_vec(),
|
||||
format: FileFormat::Csv,
|
||||
}
|
||||
}
|
||||
|
||||
/// No field mappings.
|
||||
pub(crate) fn apply_import_mapping_command(
|
||||
user_id: Uuid,
|
||||
session_id: Uuid,
|
||||
) -> ApplyImportMappingCommand {
|
||||
ApplyImportMappingCommand {
|
||||
user_id,
|
||||
session_id,
|
||||
mappings: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn apply_import_profile_command(
|
||||
user_id: Uuid,
|
||||
session_id: Uuid,
|
||||
profile_id: Uuid,
|
||||
) -> ApplyImportProfileCommand {
|
||||
ApplyImportProfileCommand {
|
||||
user_id,
|
||||
session_id,
|
||||
profile_id,
|
||||
}
|
||||
}
|
||||
|
||||
/// One confirmation, rating as given, no comment.
|
||||
pub(crate) fn confirm_watch_events_command(
|
||||
user_id: Uuid,
|
||||
watch_event_id: Uuid,
|
||||
rating: u8,
|
||||
) -> ConfirmWatchEventsCommand {
|
||||
ConfirmWatchEventsCommand {
|
||||
user_id,
|
||||
confirmations: vec![WatchEventConfirmation {
|
||||
watch_event_id,
|
||||
rating,
|
||||
comment: None,
|
||||
}],
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn dismiss_watch_events_command(
|
||||
user_id: Uuid,
|
||||
event_ids: Vec<Uuid>,
|
||||
) -> DismissWatchEventsCommand {
|
||||
DismissWatchEventsCommand { user_id, event_ids }
|
||||
}
|
||||
|
||||
/// Jellyfin provider, no label.
|
||||
pub(crate) fn generate_webhook_token_command(user_id: Uuid) -> GenerateWebhookTokenCommand {
|
||||
GenerateWebhookTokenCommand {
|
||||
user_id,
|
||||
provider: WatchEventSource::Jellyfin,
|
||||
label: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Every field unset; override what the test cares about.
|
||||
pub(crate) fn update_profile_command(user_id: Uuid) -> UpdateProfileCommand {
|
||||
UpdateProfileCommand {
|
||||
user_id,
|
||||
display_name: None,
|
||||
bio: None,
|
||||
avatar_bytes: None,
|
||||
avatar_content_type: None,
|
||||
banner_bytes: None,
|
||||
banner_content_type: None,
|
||||
also_known_as: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// All federation toggles on.
|
||||
pub(crate) fn update_user_settings_command(user_id: Uuid) -> UpdateUserSettingsCommand {
|
||||
UpdateUserSettingsCommand {
|
||||
user_id,
|
||||
federate_goals: true,
|
||||
federate_reviews: true,
|
||||
federate_watchlist: true,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn add_to_watchlist_command(user_id: Uuid, movie_id: Uuid) -> AddToWatchlistCommand {
|
||||
AddToWatchlistCommand {
|
||||
user_id,
|
||||
input: movie_input_by_id(movie_id),
|
||||
}
|
||||
}
|
||||
|
||||
/// Window is 1 Jan of `year` to 1 Jan of `year + 1`.
|
||||
pub(crate) fn request_wrap_up_command(user_id: Option<Uuid>, year: i32) -> RequestWrapUpCommand {
|
||||
RequestWrapUpCommand {
|
||||
user_id,
|
||||
start_date: NaiveDate::from_ymd_opt(year, 1, 1).unwrap(),
|
||||
end_date: NaiveDate::from_ymd_opt(year + 1, 1, 1).unwrap(),
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::test_support::register_command;
|
||||
use std::sync::Arc;
|
||||
|
||||
use domain::models::UserRole;
|
||||
@@ -23,10 +24,8 @@ async fn register_user(
|
||||
register::execute(
|
||||
®_deps,
|
||||
RegisterCommand {
|
||||
email: email.into(),
|
||||
username: username.into(),
|
||||
password: "password123".into(),
|
||||
role,
|
||||
..register_command(email, username)
|
||||
},
|
||||
)
|
||||
.await
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::test_support::register_command;
|
||||
use std::sync::Arc;
|
||||
|
||||
use domain::models::{ProfileField, User, UserProfile, UserRole};
|
||||
@@ -7,7 +8,7 @@ use domain::value_objects::{Email, PasswordHash, UserId, Username};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
auth::{commands::RegisterCommand, deps::RegisterDeps, register},
|
||||
auth::{deps::RegisterDeps, register},
|
||||
test_helpers::TestContextBuilder,
|
||||
users::{deps::GetCurrentProfileDeps, get_current_profile, queries::GetCurrentProfileQuery},
|
||||
};
|
||||
@@ -23,17 +24,9 @@ async fn returns_profile_for_existing_user() {
|
||||
config: b.config.clone(),
|
||||
};
|
||||
|
||||
register::execute(
|
||||
®_deps,
|
||||
RegisterCommand {
|
||||
email: "alice@example.com".into(),
|
||||
username: "alice".into(),
|
||||
password: "password123".into(),
|
||||
role: UserRole::Standard,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
register::execute(®_deps, register_command("alice@example.com", "alice"))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let user = users
|
||||
.find_by_email(&domain::value_objects::Email::new("alice@example.com".into()).unwrap())
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
use crate::test_support::{register_command, update_profile_command};
|
||||
use domain::errors::DomainError;
|
||||
use domain::models::UserRole;
|
||||
use domain::value_objects::Email;
|
||||
|
||||
use crate::auth::commands::RegisterCommand;
|
||||
use crate::auth::deps::RegisterDeps;
|
||||
use crate::auth::register;
|
||||
use crate::test_helpers::TestContextBuilder;
|
||||
@@ -18,17 +17,9 @@ async fn setup_user(b: &TestContextBuilder, email: &str, username: &str) {
|
||||
password_hasher: b.password_hasher.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
register::execute(
|
||||
&deps,
|
||||
RegisterCommand {
|
||||
email: email.into(),
|
||||
username: username.into(),
|
||||
password: "password123".into(),
|
||||
role: UserRole::Standard,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
register::execute(&deps, register_command(email, username))
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn deps(b: &TestContextBuilder) -> GetLocalProfileDeps {
|
||||
@@ -276,14 +267,9 @@ async fn populates_handle_and_actor_url_for_a_local_user() {
|
||||
update_profile::execute(
|
||||
&update_deps,
|
||||
UpdateProfileCommand {
|
||||
user_id: uid,
|
||||
display_name: Some("Gabriel K".into()),
|
||||
bio: Some("Movies and diaries.".into()),
|
||||
avatar_bytes: None,
|
||||
avatar_content_type: None,
|
||||
banner_bytes: None,
|
||||
banner_content_type: None,
|
||||
also_known_as: None,
|
||||
..update_profile_command(uid)
|
||||
},
|
||||
)
|
||||
.await
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use domain::models::UserRole;
|
||||
use crate::test_support::register_command;
|
||||
use domain::value_objects::{Email, FollowTarget, SocialIdentity, UserId};
|
||||
|
||||
use crate::auth::commands::RegisterCommand;
|
||||
use crate::auth::deps::RegisterDeps;
|
||||
use crate::auth::register;
|
||||
use crate::test_helpers::TestContextBuilder;
|
||||
@@ -14,17 +13,9 @@ async fn setup_user(b: &TestContextBuilder, email: &str, username: &str) -> uuid
|
||||
password_hasher: b.password_hasher.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
register::execute(
|
||||
&deps,
|
||||
RegisterCommand {
|
||||
email: email.into(),
|
||||
username: username.into(),
|
||||
password: "password123".into(),
|
||||
role: UserRole::Standard,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
register::execute(&deps, register_command(email, username))
|
||||
.await
|
||||
.unwrap();
|
||||
let user = b
|
||||
.user_repo
|
||||
.find_by_email(&Email::new(email.into()).unwrap())
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use domain::models::{ProfileField, UserRole};
|
||||
use crate::test_support::register_command;
|
||||
use domain::models::ProfileField;
|
||||
use domain::value_objects::{Email, UserId};
|
||||
|
||||
use crate::auth::commands::RegisterCommand;
|
||||
use crate::auth::deps::RegisterDeps;
|
||||
use crate::auth::register;
|
||||
use crate::test_helpers::TestContextBuilder;
|
||||
@@ -18,12 +18,7 @@ async fn get_profile_settings_includes_profile_fields() {
|
||||
};
|
||||
register::execute(
|
||||
®ister_deps,
|
||||
RegisterCommand {
|
||||
email: "settings@test.com".into(),
|
||||
username: "settingsuser".into(),
|
||||
password: "password123".into(),
|
||||
role: UserRole::Standard,
|
||||
},
|
||||
register_command("settings@test.com", "settingsuser"),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use crate::test_support::{register_command, update_profile_command};
|
||||
use std::sync::Arc;
|
||||
|
||||
use domain::events::DomainEvent;
|
||||
use domain::models::UserRole;
|
||||
use domain::ports::UserRepository;
|
||||
use domain::testing::{InMemoryUserRepository, NoopEventPublisher};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
auth::{commands::RegisterCommand, deps::RegisterDeps, register},
|
||||
auth::{deps::RegisterDeps, register},
|
||||
test_helpers::TestContextBuilder,
|
||||
users::{commands::UpdateProfileCommand, deps::UpdateProfileDeps, update_profile},
|
||||
};
|
||||
@@ -18,17 +18,9 @@ async fn register_user(b: &TestContextBuilder, users: &Arc<InMemoryUserRepositor
|
||||
password_hasher: b.password_hasher.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
register::execute(
|
||||
®_deps,
|
||||
RegisterCommand {
|
||||
email: "alice@example.com".into(),
|
||||
username: "alice".into(),
|
||||
password: "password123".into(),
|
||||
role: UserRole::Standard,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
register::execute(®_deps, register_command("alice@example.com", "alice"))
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let user = users
|
||||
.find_by_email(&domain::value_objects::Email::new("alice@example.com".into()).unwrap())
|
||||
@@ -55,14 +47,8 @@ async fn updates_display_name() {
|
||||
update_profile::execute(
|
||||
&deps,
|
||||
UpdateProfileCommand {
|
||||
user_id: uid,
|
||||
display_name: Some("Alice W.".into()),
|
||||
bio: None,
|
||||
avatar_bytes: None,
|
||||
avatar_content_type: None,
|
||||
banner_bytes: None,
|
||||
banner_content_type: None,
|
||||
also_known_as: None,
|
||||
..update_profile_command(uid)
|
||||
},
|
||||
)
|
||||
.await
|
||||
@@ -90,14 +76,9 @@ async fn rejects_invalid_avatar_content_type() {
|
||||
let result = update_profile::execute(
|
||||
&deps,
|
||||
UpdateProfileCommand {
|
||||
user_id: uid,
|
||||
display_name: None,
|
||||
bio: None,
|
||||
avatar_bytes: Some(vec![0u8; 10]),
|
||||
avatar_content_type: Some("image/gif".into()),
|
||||
banner_bytes: None,
|
||||
banner_content_type: None,
|
||||
also_known_as: None,
|
||||
..update_profile_command(uid)
|
||||
},
|
||||
)
|
||||
.await;
|
||||
@@ -122,14 +103,9 @@ async fn uploads_avatar() {
|
||||
update_profile::execute(
|
||||
&deps,
|
||||
UpdateProfileCommand {
|
||||
user_id: uid,
|
||||
display_name: None,
|
||||
bio: None,
|
||||
avatar_bytes: Some(vec![0xFFu8, 0xD8, 0xFF]),
|
||||
avatar_content_type: Some("image/jpeg".into()),
|
||||
banner_bytes: None,
|
||||
banner_content_type: None,
|
||||
also_known_as: None,
|
||||
..update_profile_command(uid)
|
||||
},
|
||||
)
|
||||
.await
|
||||
@@ -165,14 +141,9 @@ async fn uploads_banner() {
|
||||
update_profile::execute(
|
||||
&deps,
|
||||
UpdateProfileCommand {
|
||||
user_id: uid,
|
||||
display_name: None,
|
||||
bio: None,
|
||||
avatar_bytes: None,
|
||||
avatar_content_type: None,
|
||||
banner_bytes: Some(vec![0x89, 0x50, 0x4E]),
|
||||
banner_content_type: Some("image/png".into()),
|
||||
also_known_as: None,
|
||||
..update_profile_command(uid)
|
||||
},
|
||||
)
|
||||
.await
|
||||
@@ -203,14 +174,8 @@ async fn fails_for_nonexistent_user() {
|
||||
let result = update_profile::execute(
|
||||
&deps,
|
||||
UpdateProfileCommand {
|
||||
user_id: Uuid::new_v4(),
|
||||
display_name: Some("Ghost".into()),
|
||||
bio: None,
|
||||
avatar_bytes: None,
|
||||
avatar_content_type: None,
|
||||
banner_bytes: None,
|
||||
banner_content_type: None,
|
||||
also_known_as: None,
|
||||
..update_profile_command(Uuid::new_v4())
|
||||
},
|
||||
)
|
||||
.await;
|
||||
@@ -232,14 +197,9 @@ async fn rejects_invalid_banner_content_type() {
|
||||
let result = update_profile::execute(
|
||||
&deps,
|
||||
UpdateProfileCommand {
|
||||
user_id: uid,
|
||||
display_name: None,
|
||||
bio: None,
|
||||
avatar_bytes: None,
|
||||
avatar_content_type: None,
|
||||
banner_bytes: Some(vec![0u8; 10]),
|
||||
banner_content_type: Some("text/plain".into()),
|
||||
also_known_as: None,
|
||||
..update_profile_command(uid)
|
||||
},
|
||||
)
|
||||
.await;
|
||||
@@ -264,14 +224,9 @@ async fn text_only_update_emits_user_updated_no_image_stored() {
|
||||
update_profile::execute(
|
||||
&deps,
|
||||
UpdateProfileCommand {
|
||||
user_id: uid,
|
||||
display_name: Some("Alice Updated".into()),
|
||||
bio: Some("Hello world".into()),
|
||||
avatar_bytes: None,
|
||||
avatar_content_type: None,
|
||||
banner_bytes: None,
|
||||
banner_content_type: None,
|
||||
also_known_as: None,
|
||||
..update_profile_command(uid)
|
||||
},
|
||||
)
|
||||
.await
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::test_support::update_user_settings_command;
|
||||
use std::sync::Arc;
|
||||
|
||||
use domain::testing::InMemoryUserSettingsRepository;
|
||||
@@ -24,10 +25,8 @@ async fn updates_federate_goals() {
|
||||
user_settings: user_settings.clone(),
|
||||
},
|
||||
UpdateUserSettingsCommand {
|
||||
user_id: uid,
|
||||
federate_goals: false,
|
||||
federate_reviews: true,
|
||||
federate_watchlist: true,
|
||||
..update_user_settings_command(uid)
|
||||
},
|
||||
)
|
||||
.await
|
||||
@@ -53,10 +52,8 @@ async fn updates_federate_reviews() {
|
||||
user_settings: user_settings.clone(),
|
||||
},
|
||||
UpdateUserSettingsCommand {
|
||||
user_id: uid,
|
||||
federate_goals: true,
|
||||
federate_reviews: false,
|
||||
federate_watchlist: true,
|
||||
..update_user_settings_command(uid)
|
||||
},
|
||||
)
|
||||
.await
|
||||
@@ -82,10 +79,8 @@ async fn updates_federate_watchlist() {
|
||||
user_settings: user_settings.clone(),
|
||||
},
|
||||
UpdateUserSettingsCommand {
|
||||
user_id: uid,
|
||||
federate_goals: true,
|
||||
federate_reviews: true,
|
||||
federate_watchlist: false,
|
||||
..update_user_settings_command(uid)
|
||||
},
|
||||
)
|
||||
.await
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
use crate::test_support::{add_to_watchlist_command, movie_input_manual};
|
||||
use domain::testing::test_movie_with_year;
|
||||
use std::sync::Arc;
|
||||
|
||||
use domain::{
|
||||
models::Movie,
|
||||
ports::MovieCommand,
|
||||
testing::{InMemoryMovieRepository, InMemoryWatchlistRepository, NoopEventPublisher},
|
||||
value_objects::{MovieTitle, ReleaseYear},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
diary::commands::MovieInput,
|
||||
watchlist::{add, commands::AddToWatchlistCommand, deps::WatchlistAddDeps},
|
||||
};
|
||||
use crate::watchlist::{add, commands::AddToWatchlistCommand, deps::WatchlistAddDeps};
|
||||
|
||||
fn make_deps(
|
||||
movies: Arc<InMemoryMovieRepository>,
|
||||
@@ -30,28 +27,13 @@ async fn test_add_to_watchlist_resolves_and_saves() {
|
||||
let movies = InMemoryMovieRepository::new();
|
||||
let watchlist = InMemoryWatchlistRepository::new();
|
||||
|
||||
let movie = Movie::new(
|
||||
None,
|
||||
MovieTitle::new("The Thing".into()).unwrap(),
|
||||
ReleaseYear::new(1982).unwrap(),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let movie = test_movie_with_year("The Thing", 1982);
|
||||
let movie_uuid = movie.id().value();
|
||||
movies.upsert_movie(&movie).await.unwrap();
|
||||
|
||||
let deps = make_deps(Arc::clone(&movies), Arc::clone(&watchlist));
|
||||
|
||||
let cmd = AddToWatchlistCommand {
|
||||
user_id: uuid::Uuid::new_v4(),
|
||||
input: MovieInput {
|
||||
movie_id: Some(movie_uuid),
|
||||
external_metadata_id: None,
|
||||
manual_title: None,
|
||||
manual_release_year: None,
|
||||
manual_director: None,
|
||||
},
|
||||
};
|
||||
let cmd = add_to_watchlist_command(uuid::Uuid::new_v4(), movie_uuid);
|
||||
|
||||
add::execute(&deps, cmd).await.unwrap();
|
||||
|
||||
@@ -63,29 +45,14 @@ async fn test_add_to_watchlist_already_present_is_idempotent() {
|
||||
let movies = InMemoryMovieRepository::new();
|
||||
let watchlist = InMemoryWatchlistRepository::new();
|
||||
|
||||
let movie = Movie::new(
|
||||
None,
|
||||
MovieTitle::new("RoboCop".into()).unwrap(),
|
||||
ReleaseYear::new(1987).unwrap(),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let movie = test_movie_with_year("RoboCop", 1987);
|
||||
let movie_uuid = movie.id().value();
|
||||
let user_id = uuid::Uuid::new_v4();
|
||||
movies.upsert_movie(&movie).await.unwrap();
|
||||
|
||||
let deps = make_deps(Arc::clone(&movies), Arc::clone(&watchlist));
|
||||
|
||||
let make_cmd = || AddToWatchlistCommand {
|
||||
user_id,
|
||||
input: MovieInput {
|
||||
movie_id: Some(movie_uuid),
|
||||
external_metadata_id: None,
|
||||
manual_title: None,
|
||||
manual_release_year: None,
|
||||
manual_director: None,
|
||||
},
|
||||
};
|
||||
let make_cmd = || add_to_watchlist_command(user_id, movie_uuid);
|
||||
|
||||
add::execute(&deps, make_cmd()).await.unwrap();
|
||||
add::execute(&deps, make_cmd()).await.unwrap();
|
||||
@@ -102,13 +69,7 @@ async fn test_add_to_watchlist_with_manual_movie() {
|
||||
|
||||
let cmd = AddToWatchlistCommand {
|
||||
user_id: uuid::Uuid::new_v4(),
|
||||
input: MovieInput {
|
||||
movie_id: None,
|
||||
external_metadata_id: None,
|
||||
manual_title: Some("New Manual Movie".into()),
|
||||
manual_release_year: Some(2024),
|
||||
manual_director: None,
|
||||
},
|
||||
input: movie_input_manual("New Manual Movie", 2024),
|
||||
};
|
||||
|
||||
add::execute(&deps, cmd).await.unwrap();
|
||||
@@ -124,16 +85,7 @@ async fn test_add_to_watchlist_movie_not_found_by_id() {
|
||||
|
||||
let deps = make_deps(Arc::clone(&movies), Arc::clone(&watchlist));
|
||||
|
||||
let cmd = AddToWatchlistCommand {
|
||||
user_id: uuid::Uuid::new_v4(),
|
||||
input: MovieInput {
|
||||
movie_id: Some(uuid::Uuid::new_v4()),
|
||||
external_metadata_id: None,
|
||||
manual_title: None,
|
||||
manual_release_year: None,
|
||||
manual_director: None,
|
||||
},
|
||||
};
|
||||
let cmd = add_to_watchlist_command(uuid::Uuid::new_v4(), uuid::Uuid::new_v4());
|
||||
|
||||
assert!(add::execute(&deps, cmd).await.is_err());
|
||||
}
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
use crate::test_support::register_command;
|
||||
use std::sync::Arc;
|
||||
|
||||
use uuid::Uuid;
|
||||
|
||||
use domain::models::UserRole;
|
||||
use domain::testing::{
|
||||
InMemoryRemoteWatchlistRepository, InMemoryUserRepository, InMemoryWatchlistRepository,
|
||||
PanicRemoteWatchlistRepository, PanicWatchlistRepository,
|
||||
};
|
||||
use domain::value_objects::Email;
|
||||
|
||||
use crate::auth::commands::RegisterCommand;
|
||||
use crate::auth::deps::RegisterDeps;
|
||||
use crate::auth::register;
|
||||
use crate::test_helpers::TestContextBuilder;
|
||||
@@ -22,17 +21,9 @@ async fn setup_user(b: &TestContextBuilder, email: &str, username: &str) {
|
||||
password_hasher: b.password_hasher.clone(),
|
||||
config: b.config.clone(),
|
||||
};
|
||||
register::execute(
|
||||
&deps,
|
||||
RegisterCommand {
|
||||
email: email.into(),
|
||||
username: username.into(),
|
||||
password: "password123".into(),
|
||||
role: UserRole::Standard,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
register::execute(&deps, register_command(email, username))
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::test_support::request_wrap_up_command;
|
||||
use chrono::NaiveDate;
|
||||
use domain::events::DomainEvent;
|
||||
use domain::models::wrapup::{WrapUpRecord, WrapUpStatus};
|
||||
@@ -21,11 +22,7 @@ fn deps(
|
||||
}
|
||||
|
||||
fn past_cmd() -> RequestWrapUpCommand {
|
||||
RequestWrapUpCommand {
|
||||
user_id: Some(Uuid::nil()),
|
||||
start_date: NaiveDate::from_ymd_opt(2024, 1, 1).unwrap(),
|
||||
end_date: NaiveDate::from_ymd_opt(2025, 1, 1).unwrap(),
|
||||
}
|
||||
request_wrap_up_command(Some(Uuid::nil()), 2024)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -105,16 +102,9 @@ async fn replaces_failed_wrapup() {
|
||||
async fn rejects_future_end_date() {
|
||||
let repo = InMemoryWrapUpRepository::new();
|
||||
let events = NoopEventPublisher::new();
|
||||
let err = generate::execute(
|
||||
&deps(&repo, &events),
|
||||
RequestWrapUpCommand {
|
||||
user_id: None,
|
||||
start_date: NaiveDate::from_ymd_opt(2030, 1, 1).unwrap(),
|
||||
end_date: NaiveDate::from_ymd_opt(2031, 1, 1).unwrap(),
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap_err();
|
||||
let err = generate::execute(&deps(&repo, &events), request_wrap_up_command(None, 2030))
|
||||
.await
|
||||
.unwrap_err();
|
||||
|
||||
assert!(err.to_string().contains("future"));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user