fix: real AP id tests, exact poster key check, exists port, list_movies fake
This commit is contained in:
@@ -24,7 +24,7 @@ use domain::{
|
||||
FakePosterFetcher, InMemoryStore, NoopEventPublisher, NoopObjectStorage, NoopPersonCommand,
|
||||
test_movie_with_external_id,
|
||||
},
|
||||
value_objects::{ExternalMetadataId, MovieId, PosterUrl},
|
||||
value_objects::{ExternalMetadataId, MovieId, PosterPath, PosterUrl},
|
||||
};
|
||||
|
||||
use application::movies::{
|
||||
@@ -239,6 +239,32 @@ impl domain::ports::ImageFetcher for NoImages {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the key it was given, like the real adapter.
|
||||
struct KeyStorage;
|
||||
|
||||
#[async_trait]
|
||||
impl domain::ports::ObjectStorage for KeyStorage {
|
||||
async fn store(&self, key: &str, _: &[u8]) -> Result<String, DomainError> {
|
||||
Ok(key.to_string())
|
||||
}
|
||||
async fn get(&self, _: &str) -> Result<Vec<u8>, DomainError> {
|
||||
Ok(vec![])
|
||||
}
|
||||
async fn get_stream(
|
||||
&self,
|
||||
_: &str,
|
||||
) -> Result<futures::stream::BoxStream<'static, Result<bytes::Bytes, DomainError>>, DomainError>
|
||||
{
|
||||
Ok(Box::pin(futures::stream::empty()))
|
||||
}
|
||||
async fn delete(&self, _: &str) -> Result<(), DomainError> {
|
||||
Ok(())
|
||||
}
|
||||
async fn exists(&self, _: &str) -> Result<bool, DomainError> {
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
|
||||
struct MetadataWithPoster;
|
||||
|
||||
#[async_trait]
|
||||
@@ -409,7 +435,7 @@ async fn movie_discovery_indexer_is_idempotent_when_run_twice() {
|
||||
#[tokio::test]
|
||||
async fn search_reindex_is_idempotent_when_run_twice() {
|
||||
let store = InMemoryStore::new();
|
||||
seeded_movie(&store).await;
|
||||
let (movie, _) = seeded_movie(&store).await;
|
||||
let persons = FakePersons::new(person(3, "Someone"));
|
||||
let search = RecordingSearch::new();
|
||||
let handler = SearchReindexHandler::new(ReindexSearchDeps {
|
||||
@@ -430,7 +456,11 @@ async fn search_reindex_is_idempotent_when_run_twice() {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert!(!after_first.is_empty());
|
||||
assert!(
|
||||
after_first.contains(&("movie".to_string(), movie.id().value().to_string())),
|
||||
"the movie doc is indexed"
|
||||
);
|
||||
assert!(after_first.iter().any(|(k, _)| k == "person"));
|
||||
assert_eq!(search.snapshot(), after_first);
|
||||
}
|
||||
|
||||
@@ -446,7 +476,7 @@ async fn poster_sync_is_idempotent_when_run_twice() {
|
||||
store.clone(),
|
||||
Arc::new(MetadataWithPoster),
|
||||
Arc::new(FakePosterFetcher),
|
||||
Arc::new(NoopObjectStorage),
|
||||
Arc::new(KeyStorage),
|
||||
publisher.clone(),
|
||||
0,
|
||||
);
|
||||
@@ -466,3 +496,54 @@ async fn poster_sync_is_idempotent_when_run_twice() {
|
||||
assert_eq!(synced, 1, "PosterSynced fans out to federation: emit once");
|
||||
assert_eq!(publisher.published().len(), 1, "one ImageStored, not two");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn poster_sync_skips_converted_poster_keys_but_not_lookalike_paths() {
|
||||
let store = InMemoryStore::new();
|
||||
let (mut movie, ext) = seeded_movie(&store).await;
|
||||
let id = movie.id().value().to_string();
|
||||
let publisher = NoopEventPublisher::new();
|
||||
let handler = PosterSyncHandler::new(
|
||||
store.clone(),
|
||||
store.clone(),
|
||||
Arc::new(MetadataWithPoster),
|
||||
Arc::new(FakePosterFetcher),
|
||||
Arc::new(KeyStorage),
|
||||
publisher.clone(),
|
||||
0,
|
||||
);
|
||||
let event = DomainEvent::MovieDiscovered {
|
||||
movie_id: movie.id().clone(),
|
||||
external_metadata_id: ext,
|
||||
};
|
||||
|
||||
// The converter's output is the canonical synced key: skipped.
|
||||
movie.update_poster(PosterPath::new(format!("{id}.webp")).unwrap());
|
||||
store.upsert_movie(&movie, &[]).await.unwrap();
|
||||
handler.handle(&event).await.unwrap();
|
||||
assert!(publisher.published().is_empty());
|
||||
|
||||
// A foreign path that merely contains the id is not a synced poster.
|
||||
movie.update_poster(PosterPath::new(format!("https://cdn.example/{id}/p.jpg")).unwrap());
|
||||
store.upsert_movie(&movie, &[]).await.unwrap();
|
||||
handler.handle(&event).await.unwrap();
|
||||
assert_eq!(publisher.published().len(), 1);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn enrichment_of_a_deleted_movie_stores_no_profile() {
|
||||
let store = InMemoryStore::new();
|
||||
let ghost = MovieId::from_uuid(uuid::Uuid::new_v4());
|
||||
let search = RecordingSearch::new();
|
||||
let client = Arc::new(CountingMovieClient(AtomicUsize::new(0)));
|
||||
let handler = enrichment_handler(&store, client, search.clone());
|
||||
let event = DomainEvent::MovieEnrichmentRequested {
|
||||
movie_id: ghost.clone(),
|
||||
external_metadata_id: ExternalMetadataId::new("tmdb:1".into()).unwrap(),
|
||||
};
|
||||
|
||||
handler.handle(&event).await.unwrap();
|
||||
|
||||
assert!(store.get_by_movie_id(&ghost).await.unwrap().is_none());
|
||||
assert!(search.snapshot().is_empty());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user