feat: rename + delete vocabularies, blocked when in use (#30)

This commit is contained in:
2026-06-05 19:35:33 +02:00
parent 09baf2949f
commit 83a7202861
5 changed files with 392 additions and 0 deletions
+128
View File
@@ -459,3 +459,131 @@ async fn term_edit_delete_requires_auth(pool: PgPool) {
.unwrap();
assert_eq!(delete_resp.status(), StatusCode::UNAUTHORIZED);
}
#[sqlx::test(migrations = "../db/migrations")]
async fn vocabulary_edit_delete_requires_auth(pool: PgPool) {
migrate_sessions(&db::Db::from_pool(pool.clone()))
.await
.unwrap();
let app = build_app(state(pool));
let vocab_uri = "/api/admin/vocabularies/00000000-0000-0000-0000-000000000000";
let patch_resp = app
.clone()
.oneshot(
Request::builder()
.method("PATCH")
.uri(vocab_uri)
.header(header::CONTENT_TYPE, "application/json")
.body(Body::from(r#"{"key":"x"}"#))
.unwrap(),
)
.await
.unwrap();
assert_eq!(patch_resp.status(), StatusCode::UNAUTHORIZED);
let delete_resp = app
.clone()
.oneshot(
Request::builder()
.method("DELETE")
.uri(vocab_uri)
.body(Body::empty())
.unwrap(),
)
.await
.unwrap();
assert_eq!(delete_resp.status(), StatusCode::UNAUTHORIZED);
}
#[sqlx::test(migrations = "../db/migrations")]
async fn rename_and_delete_vocabulary(pool: PgPool) {
migrate_sessions(&db::Db::from_pool(pool.clone()))
.await
.unwrap();
seed_user(&pool, "ed@example.com", "pw-editor-123", Role::Editor).await;
let app = build_app(state(pool));
let cookie = login(&app, "ed@example.com", "pw-editor-123").await;
let v = send(
&app,
&cookie,
"POST",
"/api/admin/vocabularies",
Some(r#"{"key":"old"}"#),
)
.await;
let vid: serde_json::Value =
serde_json::from_slice(&v.into_body().collect().await.unwrap().to_bytes()).unwrap();
let vid = vid["id"].as_str().unwrap().to_owned();
let renamed = send(
&app,
&cookie,
"PATCH",
&format!("/api/admin/vocabularies/{vid}"),
Some(r#"{"key":"new"}"#),
)
.await;
assert_eq!(renamed.status(), StatusCode::NO_CONTENT);
let deleted = send(
&app,
&cookie,
"DELETE",
&format!("/api/admin/vocabularies/{vid}"),
None,
)
.await;
assert_eq!(deleted.status(), StatusCode::NO_CONTENT);
}
#[sqlx::test(migrations = "../db/migrations")]
async fn delete_vocabulary_with_terms_is_409(pool: PgPool) {
migrate_sessions(&db::Db::from_pool(pool.clone()))
.await
.unwrap();
seed_user(&pool, "ed@example.com", "pw-editor-123", Role::Editor).await;
let app = build_app(state(pool));
let cookie = login(&app, "ed@example.com", "pw-editor-123").await;
let v = send(
&app,
&cookie,
"POST",
"/api/admin/vocabularies",
Some(r#"{"key":"material"}"#),
)
.await;
let vid: serde_json::Value =
serde_json::from_slice(&v.into_body().collect().await.unwrap().to_bytes()).unwrap();
let vid = vid["id"].as_str().unwrap().to_owned();
send(
&app,
&cookie,
"POST",
&format!("/api/admin/vocabularies/{vid}/terms"),
Some(r#"{"external_uri":null,"labels":[{"lang":"sv","label":"Trä"}]}"#),
)
.await;
let blocked = send(
&app,
&cookie,
"DELETE",
&format!("/api/admin/vocabularies/{vid}"),
None,
)
.await;
assert_eq!(blocked.status(), StatusCode::CONFLICT);
let body: serde_json::Value =
serde_json::from_slice(&blocked.into_body().collect().await.unwrap().to_bytes()).unwrap();
assert_eq!(body["count"], 1);
}