118 lines
3.6 KiB
Rust
118 lines
3.6 KiB
Rust
use domain::entities::{
|
|
Asset, AssetMetadata, AssetStack, AssetType, DerivativeAsset, DerivativeProfile,
|
|
DetectionMethod, DuplicateGroup, DuplicateStatus, GenerationStatus,
|
|
MetadataSource, SourceReference, StackMemberRole, StackType,
|
|
};
|
|
use domain::errors::DomainError;
|
|
use domain::value_objects::{Checksum, MetadataValue, StructuredData, SystemId};
|
|
|
|
// --- Asset ---
|
|
|
|
fn make_asset() -> Asset {
|
|
let src = SourceReference {
|
|
volume_id: SystemId::new(),
|
|
relative_path: "photos/img.jpg".to_string(),
|
|
checksum: Checksum::new("a".repeat(64)).unwrap(),
|
|
};
|
|
Asset::new(src, AssetType::Image, "image/jpeg", 1024, SystemId::new())
|
|
}
|
|
|
|
#[test]
|
|
fn new_asset_is_unprocessed() {
|
|
let a = make_asset();
|
|
assert!(!a.is_processed);
|
|
}
|
|
|
|
#[test]
|
|
fn mark_processed() {
|
|
let mut a = make_asset();
|
|
a.mark_processed();
|
|
assert!(a.is_processed);
|
|
}
|
|
|
|
// --- AssetMetadata ---
|
|
|
|
#[test]
|
|
fn metadata_source_ordering() {
|
|
assert!(MetadataSource::ExifExtracted < MetadataSource::AiGenerated);
|
|
assert!(MetadataSource::AiGenerated < MetadataSource::UserEdited);
|
|
}
|
|
|
|
#[test]
|
|
fn create_metadata_layer() {
|
|
let mut data = StructuredData::new();
|
|
data.insert("camera", MetadataValue::String("Canon".to_string()));
|
|
let meta = AssetMetadata::new(SystemId::new(), MetadataSource::ExifExtracted, data);
|
|
assert_eq!(meta.metadata_source, MetadataSource::ExifExtracted);
|
|
assert_eq!(meta.data.get_string("camera"), Some("Canon"));
|
|
}
|
|
|
|
// --- AssetStack ---
|
|
|
|
#[test]
|
|
fn new_stack_contains_primary() {
|
|
let primary = SystemId::new();
|
|
let stack = AssetStack::new(StackType::LivePhoto, primary.clone(), SystemId::new());
|
|
assert_eq!(stack.members.len(), 1);
|
|
assert_eq!(stack.members[0].asset_id, primary);
|
|
assert_eq!(stack.members[0].role, StackMemberRole::PrimaryDisplay);
|
|
assert_eq!(stack.members[0].sort_order, 0);
|
|
}
|
|
|
|
#[test]
|
|
fn add_motion_clip() {
|
|
let mut stack = AssetStack::new(StackType::LivePhoto, SystemId::new(), SystemId::new());
|
|
let clip_id = SystemId::new();
|
|
stack.add_member(clip_id.clone(), StackMemberRole::MotionClip).unwrap();
|
|
assert_eq!(stack.members.len(), 2);
|
|
assert_eq!(stack.members[1].asset_id, clip_id);
|
|
assert_eq!(stack.members[1].sort_order, 1);
|
|
}
|
|
|
|
#[test]
|
|
fn cannot_add_duplicate_to_stack() {
|
|
let primary = SystemId::new();
|
|
let mut stack = AssetStack::new(StackType::LivePhoto, primary.clone(), SystemId::new());
|
|
let result = stack.add_member(primary, StackMemberRole::HighResSource);
|
|
assert!(matches!(result, Err(DomainError::Conflict(_))));
|
|
}
|
|
|
|
// --- DerivativeAsset ---
|
|
|
|
#[test]
|
|
fn derivative_lifecycle() {
|
|
let mut d = DerivativeAsset::new_pending(
|
|
SystemId::new(),
|
|
DerivativeProfile::ThumbnailSquare,
|
|
"/thumbs/abc.webp",
|
|
);
|
|
assert_eq!(d.generation_status, GenerationStatus::Pending);
|
|
assert_eq!(d.file_size, 0);
|
|
assert_eq!(d.dimensions, (0, 0));
|
|
|
|
d.mark_ready("image/webp", 4096, (256, 256));
|
|
assert_eq!(d.generation_status, GenerationStatus::Ready);
|
|
assert_eq!(d.mime_type, "image/webp");
|
|
assert_eq!(d.file_size, 4096);
|
|
assert_eq!(d.dimensions, (256, 256));
|
|
}
|
|
|
|
// --- Duplicate ---
|
|
|
|
#[test]
|
|
fn exact_duplicate_group() {
|
|
let g = DuplicateGroup::new_exact(SystemId::new(), SystemId::new());
|
|
assert_eq!(g.detection_method, DetectionMethod::ExactHash);
|
|
assert_eq!(g.status, DuplicateStatus::Unresolved);
|
|
assert_eq!(g.candidates.len(), 2);
|
|
assert_eq!(g.candidates[0].similarity_score, 1.0);
|
|
assert_eq!(g.candidates[1].similarity_score, 1.0);
|
|
}
|
|
|
|
#[test]
|
|
fn resolve_group() {
|
|
let mut g = DuplicateGroup::new_exact(SystemId::new(), SystemId::new());
|
|
g.resolve();
|
|
assert_eq!(g.status, DuplicateStatus::Resolved);
|
|
}
|