use std::sync::Arc; use application::catalog::{UpdateMetadataCommand, UpdateMetadataHandler}; use application::testing::{InMemoryAssetRepository, InMemoryAssetMetadataRepository, StubEventPublisher}; use domain::catalog::entities::{Asset, AssetType, SourceReference, MetadataSource}; use domain::errors::DomainError; use domain::value_objects::{Checksum, MetadataValue, StructuredData, SystemId}; async fn seed_asset(repo: &InMemoryAssetRepository) -> Asset { let source = SourceReference { volume_id: SystemId::new(), relative_path: "photos/img.jpg".into(), checksum: Checksum::new("a".repeat(64)).unwrap(), }; let asset = Asset::new(source, AssetType::Image, "image/jpeg", 1024, SystemId::new()); repo.save(&asset).await.unwrap(); asset } use domain::ports::AssetRepository; #[tokio::test] async fn updates_metadata() { let asset_repo = Arc::new(InMemoryAssetRepository::new()); let meta_repo = Arc::new(InMemoryAssetMetadataRepository::new()); let events = Arc::new(StubEventPublisher::new()); let asset = seed_asset(&asset_repo).await; let handler = UpdateMetadataHandler::new( asset_repo.clone(), meta_repo.clone(), events.clone(), ); let mut data = StructuredData::new(); data.insert("title", MetadataValue::String("Sunset".into())); let result = handler.execute(UpdateMetadataCommand { asset_id: asset.asset_id, user_id: SystemId::new(), data, }).await.unwrap(); assert_eq!(result.metadata_source, MetadataSource::UserEdited); assert_eq!(result.data.get_string("title"), Some("Sunset")); assert_eq!(events.published().await.len(), 1); } #[tokio::test] async fn rejects_nonexistent_asset() { let asset_repo = Arc::new(InMemoryAssetRepository::new()); let meta_repo = Arc::new(InMemoryAssetMetadataRepository::new()); let events = Arc::new(StubEventPublisher::new()); let handler = UpdateMetadataHandler::new(asset_repo, meta_repo, events); let result = handler.execute(UpdateMetadataCommand { asset_id: SystemId::new(), user_id: SystemId::new(), data: StructuredData::new(), }).await; assert!(matches!(result, Err(DomainError::NotFound(_)))); }