use db::{Db, authority, catalog, fields}; use domain::{ AuditActor, AuthorityKind, LocalizedLabel, NewAuthority, NewFieldDefinition, Visibility, }; use sqlx::PgPool; fn sample_object_input() -> domain::ObjectInput { domain::ObjectInput { object_number: "X.1".into(), object_name: "Test".into(), number_of_objects: 1, brief_description: None, current_location: None, current_owner: None, recorder: None, recording_date: None, visibility: Visibility::Draft, } } fn new_person(name_sv: &str, name_en: &str) -> NewAuthority { NewAuthority { kind: AuthorityKind::Person, external_uri: None, labels: vec![ LocalizedLabel { lang: "sv".into(), label: name_sv.into(), }, LocalizedLabel { lang: "en".into(), label: name_en.into(), }, ], } } #[sqlx::test] async fn authority_round_trips_with_labels(pool: PgPool) { let db = Db::from_pool(pool); let mut tx = db.pool().begin().await.unwrap(); let id = authority::create_authority( &mut tx, AuditActor::System, &new_person("Carl Larsson", "Carl Larsson"), ) .await .unwrap(); tx.commit().await.unwrap(); let got = authority::authority_by_id(db.pool(), id) .await .unwrap() .unwrap(); assert_eq!(got.id, id); assert_eq!(got.kind, AuthorityKind::Person); assert_eq!(got.labels.len(), 2); assert_eq!( domain::pick_label(&got.labels, "sv", "en"), Some("Carl Larsson") ); } #[sqlx::test] async fn list_by_kind_filters(pool: PgPool) { let db = Db::from_pool(pool); let mut tx = db.pool().begin().await.unwrap(); authority::create_authority(&mut tx, AuditActor::System, &new_person("A", "A")) .await .unwrap(); authority::create_authority( &mut tx, AuditActor::System, &NewAuthority { kind: AuthorityKind::Place, external_uri: None, labels: vec![LocalizedLabel { lang: "en".into(), label: "Stockholm".into(), }], }, ) .await .unwrap(); tx.commit().await.unwrap(); let people = authority::list_by_kind(db.pool(), AuthorityKind::Person) .await .unwrap(); assert_eq!(people.len(), 1); assert_eq!(people[0].kind, AuthorityKind::Person); let places = authority::list_by_kind(db.pool(), AuthorityKind::Place) .await .unwrap(); assert_eq!(places.len(), 1); assert_eq!(places[0].kind, AuthorityKind::Place); } #[sqlx::test] async fn resolve_authority_returns_kind(pool: PgPool) { let db = Db::from_pool(pool); let mut tx = db.pool().begin().await.unwrap(); let id = authority::create_authority(&mut tx, AuditActor::System, &new_person("X", "X")) .await .unwrap(); tx.commit().await.unwrap(); let r = authority::resolve_authority(db.pool(), id) .await .unwrap() .unwrap(); assert_eq!(r.authority_id(), id); assert_eq!(r.kind(), AuthorityKind::Person); let missing = authority::resolve_authority(db.pool(), domain::AuthorityId::new()) .await .unwrap(); assert!(missing.is_none()); } #[sqlx::test] async fn authority_with_no_labels_round_trips_empty(pool: PgPool) { let db = Db::from_pool(pool); let mut tx = db.pool().begin().await.unwrap(); let id = authority::create_authority( &mut tx, AuditActor::System, &NewAuthority { kind: AuthorityKind::Organisation, external_uri: None, labels: vec![], }, ) .await .unwrap(); tx.commit().await.unwrap(); let got = authority::authority_by_id(db.pool(), id) .await .unwrap() .unwrap(); assert_eq!(got.kind, AuthorityKind::Organisation); assert!(got.labels.is_empty()); } #[sqlx::test(migrations = "../db/migrations")] async fn update_authority_changes_labels(pool: PgPool) { let db = Db::from_pool(pool); let mut tx = db.pool().begin().await.unwrap(); let id = authority::create_authority( &mut tx, AuditActor::System, &NewAuthority { kind: AuthorityKind::Person, external_uri: None, labels: vec![LocalizedLabel { lang: "sv".into(), label: "Anon".into(), }], }, ) .await .unwrap(); let existed = authority::update_authority( &mut tx, AuditActor::System, id, Some("https://viaf.org/1"), &[LocalizedLabel { lang: "sv".into(), label: "Astrid".into(), }], ) .await .unwrap(); assert!(existed); tx.commit().await.unwrap(); let a = authority::authority_by_id(db.pool(), id) .await .unwrap() .unwrap(); assert_eq!(a.external_uri.as_deref(), Some("https://viaf.org/1")); assert_eq!(a.labels[0].label, "Astrid"); } #[sqlx::test(migrations = "../db/migrations")] async fn delete_authority_blocks_when_referenced(pool: PgPool) { use db::DeleteOutcome; let db = Db::from_pool(pool); let mut tx = db.pool().begin().await.unwrap(); let id = authority::create_authority( &mut tx, AuditActor::System, &NewAuthority { kind: AuthorityKind::Person, external_uri: None, labels: vec![LocalizedLabel { lang: "sv".into(), label: "Astrid".into(), }], }, ) .await .unwrap(); fields::create_field_definition( &mut tx, &NewFieldDefinition { key: "maker".into(), field_type: domain::FieldType::Authority { kind: Some(AuthorityKind::Person), }, required: false, group_key: None, labels: vec![LocalizedLabel { lang: "sv".into(), label: "Tillverkare".into(), }], }, ) .await .unwrap(); let obj = catalog::create_object(&mut tx, AuditActor::System, &sample_object_input()) .await .unwrap(); let mut map = serde_json::Map::new(); map.insert("maker".into(), serde_json::Value::String(id.to_string())); catalog::set_object_fields(&mut tx, AuditActor::System, obj, &map) .await .unwrap(); assert_eq!( authority::delete_authority(&mut tx, AuditActor::System, id) .await .unwrap(), DeleteOutcome::InUse { count: 1 } ); catalog::set_object_fields(&mut tx, AuditActor::System, obj, &serde_json::Map::new()) .await .unwrap(); assert_eq!( authority::delete_authority(&mut tx, AuditActor::System, id) .await .unwrap(), DeleteOutcome::Deleted ); assert_eq!( authority::delete_authority(&mut tx, AuditActor::System, id) .await .unwrap(), DeleteOutcome::NotFound ); }