use application::sidecar::{FullImportCommand, FullImportHandler}; use application::testing::{ InMemoryAssetMetadataRepository, InMemoryAssetRepository, InMemorySidecarRepository, InMemorySidecarWriter, }; use domain::catalog::entities::{Asset, AssetType, MetadataSource, SourceReference}; use domain::entities::SidecarRecord; use domain::ports::{ AssetMetadataRepository, AssetRepository, SidecarRepository, SidecarWriterPort, }; use domain::value_objects::{Checksum, MetadataValue, StructuredData, SystemId}; use std::sync::Arc; fn make_asset(owner: SystemId) -> Asset { let source = SourceReference { volume_id: SystemId::new(), relative_path: "photos/img.jpg".into(), checksum: Checksum::new("b".repeat(64)).unwrap(), }; Asset::new(source, AssetType::Image, "image/jpeg", 2048, owner) } #[tokio::test] async fn imports_from_existing_sidecars() { let asset_repo = Arc::new(InMemoryAssetRepository::new()); let meta_repo = Arc::new(InMemoryAssetMetadataRepository::new()); let sidecar_repo = Arc::new(InMemorySidecarRepository::new()); let writer = Arc::new(InMemorySidecarWriter::new()); let owner = SystemId::new(); let asset = make_asset(owner); asset_repo.save(&asset).await.unwrap(); let path = format!("sidecars/{}.xmp", asset.asset_id); let record = SidecarRecord::new(asset.asset_id, &path); sidecar_repo.save(&record).await.unwrap(); let mut data = StructuredData::new(); data.insert("lens", MetadataValue::String("50mm".into())); writer.write_sidecar(&data, &path).await.unwrap(); let handler = FullImportHandler::new(asset_repo, meta_repo.clone(), sidecar_repo, writer); let count = handler .execute(FullImportCommand { owner_id: owner }) .await .unwrap(); assert_eq!(count, 1); let imported = meta_repo .find_by_asset_and_source(&asset.asset_id, MetadataSource::ExifExtracted) .await .unwrap(); assert!(imported.is_some()); assert_eq!(imported.unwrap().data.get_string("lens"), Some("50mm")); } #[tokio::test] async fn skips_missing_sidecars() { let asset_repo = Arc::new(InMemoryAssetRepository::new()); let meta_repo = Arc::new(InMemoryAssetMetadataRepository::new()); let sidecar_repo = Arc::new(InMemorySidecarRepository::new()); let writer = Arc::new(InMemorySidecarWriter::new()); let owner = SystemId::new(); let asset = make_asset(owner); asset_repo.save(&asset).await.unwrap(); // No sidecar record, no sidecar file let handler = FullImportHandler::new(asset_repo, meta_repo, sidecar_repo, writer); let count = handler .execute(FullImportCommand { owner_id: owner }) .await .unwrap(); assert_eq!(count, 0); }