This commit is contained in:
2025-10-31 01:26:24 +01:00
parent fa43bc749e
commit 722c2f9a5c
14 changed files with 6497 additions and 6377 deletions
+4 -2
View File
@@ -53,8 +53,10 @@ struct SignupStartResponse {
#[derive(Deserialize)]
struct TenantSelectionResponse {
access_token: String,
tenants: Vec<TenantSummary>,
#[serde(rename = "access_token")]
_access_token: String,
#[serde(rename = "tenants")]
_tenants: Vec<TenantSummary>,
}
#[derive(Deserialize)]
+56
View File
@@ -693,6 +693,62 @@ pub async fn body_to_vec(body: Body) -> Result<Vec<u8>> {
Ok(collected.to_bytes().to_vec())
}
#[cfg(test)]
mod helper_tests {
use super::*;
#[tokio::test]
async fn create_session_and_login_token_provide_access() -> Result<()> {
let _lock = acquire_db_lock().await;
let app = TestApp::new().await?;
let username = "helper-login";
let password = "irrelevant";
app.insert_user(username, password, "admin").await?;
let (access, refresh, refresh_id) = app.create_session(username).await?;
assert!(!access.is_empty(), "access token should not be empty");
assert!(!refresh.is_empty(), "refresh token should not be empty");
assert_ne!(refresh_id, Uuid::nil(), "refresh token id should be assigned");
let bearer = app.login_token(username, password).await?;
assert!(!bearer.is_empty(), "login_token must yield bearer");
app.cleanup().await?;
Ok(())
}
#[tokio::test]
async fn insert_passkey_and_upload_with_options_succeeds() -> Result<()> {
let _lock = acquire_db_lock().await;
let app = TestApp::new().await?;
let username = "helper-passkey";
let password = "unused";
let user_id = app.insert_user(username, password, "admin").await?;
let passkey_id = app.insert_passkey(user_id, Some("Laptop")).await?;
assert_ne!(passkey_id, Uuid::nil());
let bearer = app.login_token(username, password).await?;
let response = app
.upload_document_with_options(
"/api/documents",
"helper.txt",
"text/plain",
b"helper-content",
None,
Some("Helper Note"),
Some("{\"category\":\"note\"}"),
&bearer,
)
.await?;
assert!(response.status().is_success());
app.cleanup().await?;
Ok(())
}
}
async fn prepare_database(pool: &PgPool) -> Result<()> {
let pool = pool.clone();
tokio::task::spawn_blocking(move || -> Result<()> {
+2 -1
View File
@@ -14,7 +14,8 @@ struct DocumentDetail {
#[derive(Deserialize)]
struct DocumentSummary {
id: Uuid,
title: String,
#[serde(rename = "title")]
_title: String,
#[serde(default)]
correspondents: Vec<DocumentCorrespondentSummary>,
}
+25 -12
View File
@@ -25,12 +25,8 @@ struct DocumentInfo {
metadata: Value,
#[serde(default)]
document_type_id: Option<Uuid>,
#[serde(default)]
document_type: Option<DocumentTypeInfo>,
tags: Vec<TagSummary>,
#[serde(default)]
correspondents: Vec<DocumentCorrespondentInfo>,
#[serde(default)]
current_version: Option<DocumentVersionPayload>,
}
@@ -63,8 +59,6 @@ struct DocumentListItem {
#[serde(default)]
document_type_id: Option<Uuid>,
#[serde(default)]
document_type: Option<DocumentTypeInfo>,
#[serde(default)]
current_version: Option<DocumentVersionPayload>,
}
@@ -89,12 +83,6 @@ struct TagSummary {
label: String,
}
#[derive(Deserialize)]
struct DocumentCorrespondentInfo {
id: Uuid,
name: String,
}
#[derive(Deserialize)]
struct DocumentTypeInfo {
id: Uuid,
@@ -196,6 +184,7 @@ async fn upload_and_list_document() -> Result<()> {
assert_eq!(detail.document.title, "doc");
assert_eq!(detail.document.deleted_at, None);
assert!(detail.document.issued_at.is_none());
assert!(detail.document.document_type_id.is_none());
assert!(detail.document.tags.is_empty());
let current_version = detail
.document
@@ -1490,6 +1479,8 @@ async fn list_documents_filtered_by_document_type() -> Result<()> {
assert_eq!(receipts_resp.status(), StatusCode::CREATED);
let receipts_body = body_to_vec(receipts_resp.into_body()).await?;
let receipts: DocumentTypeInfo = serde_json::from_slice(&receipts_body)?;
assert_eq!(invoices.name, "Invoices");
assert_eq!(receipts.name, "Receipts");
let doc_a = app
.upload_document(
@@ -1591,6 +1582,28 @@ async fn list_documents_filtered_by_document_type() -> Result<()> {
assert!(combined_ids.contains(&detail_b.document.id));
assert!(!combined_ids.contains(&detail_c.document.id));
let refreshed_a = app
.get(
&format!("/api/documents/{}", detail_a.document.id),
Some(&token),
)
.await?;
assert!(refreshed_a.status().is_success());
let refreshed_a_body = body_to_vec(refreshed_a.into_body()).await?;
let refreshed_a_detail: DocumentDetail = serde_json::from_slice(&refreshed_a_body)?;
assert_eq!(refreshed_a_detail.document.document_type_id, Some(invoices.id));
let refreshed_b = app
.get(
&format!("/api/documents/{}", detail_b.document.id),
Some(&token),
)
.await?;
assert!(refreshed_b.status().is_success());
let refreshed_b_body = body_to_vec(refreshed_b.into_body()).await?;
let refreshed_b_detail: DocumentDetail = serde_json::from_slice(&refreshed_b_body)?;
assert_eq!(refreshed_b_detail.document.document_type_id, Some(receipts.id));
app.cleanup().await?;
Ok(())
}