Refactor case pages into two distinct routes
This commit separates the case detail page into two distinct routes:
`/web/cases/{case_id}` for the main case information and document, and
`/web/cases/{case_id}/recordings` for a dedicated view of audio files
and their transcripts.
This change improves the organization and clarity of the case viewing
experience by segmenting the related but distinct information into their
own UI sections.
This commit is contained in:
@@ -557,39 +557,6 @@ async fn recovery_skips_completed_analysis() {
|
||||
);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Document view
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
#[tokio::test]
|
||||
async fn document_view_reads_document() {
|
||||
let config = config_with_llm(unique_tmp("dv"), "http://unused".into());
|
||||
let case_id = "11111111-1111-1111-1111-111111111111";
|
||||
let case_dir = seed_case(&config.data_path, "dr_a", case_id);
|
||||
std::fs::write(case_dir.join("document.md"), "der Inhalt").unwrap();
|
||||
|
||||
let app = doctate_server::create_router(config);
|
||||
let cookie = login(app.clone(), "dr_a").await;
|
||||
|
||||
let resp = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.uri(format!("/web/cases/{case_id}/document"))
|
||||
.header(header::COOKIE, &cookie)
|
||||
.body(Body::empty())
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
let body = axum::body::to_bytes(resp.into_body(), usize::MAX)
|
||||
.await
|
||||
.unwrap();
|
||||
let body_str = String::from_utf8(body.to_vec()).unwrap();
|
||||
assert!(body_str.contains("der Inhalt"), "expected content in body");
|
||||
assert!(body_str.contains("Dokument"));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Re-analysis path: same handler, version derived from existing documents
|
||||
// ---------------------------------------------------------------------
|
||||
@@ -827,28 +794,6 @@ async fn recovery_skips_deleted_cases() {
|
||||
assert!(rx.try_recv().is_err(), "deleted case must not be enqueued");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn document_view_without_document_returns_404() {
|
||||
let config = config_with_llm(unique_tmp("dv2"), "http://unused".into());
|
||||
let case_id = "11111111-1111-1111-1111-111111111111";
|
||||
seed_case(&config.data_path, "dr_a", case_id);
|
||||
|
||||
let app = doctate_server::create_router(config);
|
||||
let cookie = login(app.clone(), "dr_a").await;
|
||||
|
||||
let resp = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.uri(format!("/web/cases/{case_id}/document"))
|
||||
.header(header::COOKIE, &cookie)
|
||||
.body(Body::empty())
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Admin-only reset
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
@@ -27,80 +27,6 @@ fn test_config() -> Arc<Config> {
|
||||
})
|
||||
}
|
||||
|
||||
async fn body_to_string(response: axum::response::Response) -> String {
|
||||
let bytes = axum::body::to_bytes(response.into_body(), usize::MAX)
|
||||
.await
|
||||
.unwrap();
|
||||
String::from_utf8(bytes.to_vec()).unwrap()
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn web_index_empty() {
|
||||
let config = test_config();
|
||||
let app = doctate_server::create_router(config);
|
||||
|
||||
let response = app
|
||||
.oneshot(Request::builder().uri("/web/").body(Body::empty()).unwrap())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
let body = body_to_string(response).await;
|
||||
assert!(body.contains("No cases found"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn web_index_shows_cases() {
|
||||
let config = test_config();
|
||||
let data_path = config.data_path.clone();
|
||||
|
||||
// Pre-create cases on disk
|
||||
let case1 = "550e8400-e29b-41d4-a716-446655440000";
|
||||
let case2 = "660e8400-e29b-41d4-a716-446655440000";
|
||||
|
||||
let open_case = data_path.join("dr_test").join(case1);
|
||||
std::fs::create_dir_all(&open_case).unwrap();
|
||||
std::fs::write(open_case.join("2026-04-13T10-30-00Z.m4a"), b"fake audio 1").unwrap();
|
||||
|
||||
let done_case = data_path.join("dr_test").join(case2);
|
||||
std::fs::create_dir_all(&done_case).unwrap();
|
||||
std::fs::write(done_case.join("2026-04-12T09-00-00Z.m4a"), b"fake audio 2").unwrap();
|
||||
std::fs::write(
|
||||
done_case.join("2026-04-12T09-00-00Z.transcript.txt"),
|
||||
"Herzkatheter ohne Befund.",
|
||||
)
|
||||
.unwrap();
|
||||
std::fs::write(done_case.join("oneliner.txt"), "Herzkatheter unauffällig").unwrap();
|
||||
|
||||
let app = doctate_server::create_router(config);
|
||||
let response = app
|
||||
.oneshot(Request::builder().uri("/web/").body(Body::empty()).unwrap())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
let body = body_to_string(response).await;
|
||||
|
||||
assert!(body.contains(case1));
|
||||
assert!(body.contains(case2));
|
||||
assert!(body.contains("dr_test"));
|
||||
assert!(body.contains("<audio"));
|
||||
assert!(body.contains("2026-04-13T10-30-00Z.m4a"));
|
||||
// case1 has no transcript → pending placeholder
|
||||
assert!(body.contains("Transcription pending"));
|
||||
// case2 has a transcript → rendered
|
||||
assert!(body.contains("Herzkatheter ohne Befund."));
|
||||
// case2 has an oneliner → rendered exactly once (case1 has none)
|
||||
assert!(body.contains("Herzkatheter unauffällig"));
|
||||
assert_eq!(
|
||||
body.matches("class=\"oneliner\"").count(),
|
||||
1,
|
||||
"expected exactly one oneliner div"
|
||||
);
|
||||
|
||||
let _ = std::fs::remove_dir_all(&data_path);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn web_audio_serves_file() {
|
||||
let config = test_config();
|
||||
|
||||
Reference in New Issue
Block a user