test: cover resolve_library_param and per-library ExifDao filter
Adds 9 unit tests around the library plumbing: - resolve_library_param branches (absent, empty/whitespace, numeric id, name, unknown id, unknown name) - Library::resolve symmetry with strip_root - ExifDao::get_all_with_date_taken in union and scoped modes Introduces SqliteExifDao::from_connection test constructor mirroring the existing preview_dao pattern so DAO tests can drive an in-memory SQLite. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -403,6 +403,13 @@ impl SqliteExifDao {
|
||||
connection: Arc::new(Mutex::new(connect())),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn from_connection(conn: SqliteConnection) -> Self {
|
||||
SqliteExifDao {
|
||||
connection: Arc::new(Mutex::new(conn)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ExifDao for SqliteExifDao {
|
||||
@@ -927,3 +934,92 @@ impl ExifDao for SqliteExifDao {
|
||||
.map_err(|_| DbError::new(DbErrorKind::QueryError))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod exif_dao_tests {
|
||||
use super::*;
|
||||
use crate::database::models::InsertLibrary;
|
||||
use crate::database::test::in_memory_db_connection;
|
||||
|
||||
fn ctx() -> opentelemetry::Context {
|
||||
opentelemetry::Context::new()
|
||||
}
|
||||
|
||||
fn insert_row(dao: &mut SqliteExifDao, lib_id: i32, rel: &str, date: Option<i64>) {
|
||||
dao.store_exif(
|
||||
&ctx(),
|
||||
InsertImageExif {
|
||||
library_id: lib_id,
|
||||
file_path: rel.to_string(),
|
||||
camera_make: None,
|
||||
camera_model: None,
|
||||
lens_model: None,
|
||||
width: None,
|
||||
height: None,
|
||||
orientation: None,
|
||||
gps_latitude: None,
|
||||
gps_longitude: None,
|
||||
gps_altitude: None,
|
||||
focal_length: None,
|
||||
aperture: None,
|
||||
shutter_speed: None,
|
||||
iso: None,
|
||||
date_taken: date,
|
||||
created_time: 0,
|
||||
last_modified: 0,
|
||||
content_hash: None,
|
||||
size_bytes: None,
|
||||
},
|
||||
)
|
||||
.expect("insert exif row");
|
||||
}
|
||||
|
||||
fn setup_two_libraries() -> SqliteExifDao {
|
||||
let mut conn = in_memory_db_connection();
|
||||
// Migration seeds library id=1 with a placeholder root; add id=2.
|
||||
diesel::insert_into(schema::libraries::table)
|
||||
.values(InsertLibrary {
|
||||
name: "archive",
|
||||
root_path: "/tmp/archive",
|
||||
created_at: 0,
|
||||
})
|
||||
.execute(&mut conn)
|
||||
.expect("seed second library");
|
||||
SqliteExifDao::from_connection(conn)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_all_with_date_taken_union_returns_all_libraries() {
|
||||
let mut dao = setup_two_libraries();
|
||||
insert_row(&mut dao, 1, "main/a.jpg", Some(100));
|
||||
insert_row(&mut dao, 2, "archive/b.jpg", Some(200));
|
||||
// Row without a date must be excluded even in union mode.
|
||||
insert_row(&mut dao, 2, "archive/c.jpg", None);
|
||||
|
||||
let mut rows = dao.get_all_with_date_taken(&ctx(), None).unwrap();
|
||||
rows.sort_by_key(|(_, ts)| *ts);
|
||||
assert_eq!(
|
||||
rows,
|
||||
vec![
|
||||
("main/a.jpg".to_string(), 100),
|
||||
("archive/b.jpg".to_string(), 200),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn get_all_with_date_taken_scopes_by_library_id() {
|
||||
let mut dao = setup_two_libraries();
|
||||
insert_row(&mut dao, 1, "main/a.jpg", Some(100));
|
||||
insert_row(&mut dao, 2, "archive/b.jpg", Some(200));
|
||||
insert_row(&mut dao, 2, "archive/c.jpg", Some(300));
|
||||
|
||||
let lib2 = dao.get_all_with_date_taken(&ctx(), Some(2)).unwrap();
|
||||
let mut paths: Vec<String> = lib2.into_iter().map(|(p, _)| p).collect();
|
||||
paths.sort();
|
||||
assert_eq!(paths, vec!["archive/b.jpg", "archive/c.jpg"]);
|
||||
|
||||
let lib1 = dao.get_all_with_date_taken(&ctx(), Some(1)).unwrap();
|
||||
assert_eq!(lib1, vec![("main/a.jpg".to_string(), 100)]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user