refactor(tests): migrate remaining batches to tests/common/
Finishes the lift of shared helpers into `tests/common/`. Covered: - health, web, oneliners_api, upload (31 tests; upload exercises the new `multipart_upload_body` helper driven by doctate_common field constants) - sse_integration, sse_cleanup, transcribe, oneliner_heal_decoupled, silent_case_empty, failed_only_case_empty_oneliner, transient_failure_retries (24 tests) Also applied cargo fmt across the test tree and fixed one clippy needless_borrows_for_generic_args warning in analyze_test. All 387 tests pass; 3 ignored (as before). Side effect: health_test previously used a hardcoded `/tmp/doctate-test` data path, which parallel `cargo test` runs could collide on. The migration replaces it with the common unique-tmpdir pattern, removing a latent flake.
This commit is contained in:
+26
-109
@@ -1,33 +1,16 @@
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
mod common;
|
||||
|
||||
use axum::body::Body;
|
||||
use axum::http::{Request, StatusCode};
|
||||
use tower::util::ServiceExt;
|
||||
|
||||
use doctate_server::config::{Config, User};
|
||||
use common::{TestConfig, header_opt, test_user};
|
||||
|
||||
fn test_config() -> Arc<Config> {
|
||||
let data_path = std::env::temp_dir().join(format!(
|
||||
"doctate-web-test-{}-{}",
|
||||
std::process::id(),
|
||||
uuid::Uuid::new_v4()
|
||||
));
|
||||
Arc::new(Config {
|
||||
data_path,
|
||||
users: vec![User {
|
||||
slug: "dr_test".into(),
|
||||
api_key: "test-key".into(),
|
||||
web_password: "unused".into(),
|
||||
role: "doctor".into(),
|
||||
whisper: Default::default(),
|
||||
retention: Default::default(),
|
||||
window_hours: 72,
|
||||
preview_lines: 2,
|
||||
}],
|
||||
api_keys: HashMap::from([("test-key".into(), "dr_test".into())]),
|
||||
..Config::test_default()
|
||||
})
|
||||
fn test_config() -> std::sync::Arc<doctate_server::config::Config> {
|
||||
TestConfig::new()
|
||||
.with_label("web")
|
||||
.with_user(test_user("dr_test"))
|
||||
.build()
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -36,8 +19,7 @@ async fn web_audio_serves_file() {
|
||||
let data_path = config.data_path.clone();
|
||||
|
||||
let case_id = "770e8400-e29b-41d4-a716-446655440000";
|
||||
let case_dir = data_path.join("dr_test").join(case_id);
|
||||
std::fs::create_dir_all(&case_dir).unwrap();
|
||||
let case_dir = common::seed_case(&data_path, "dr_test", case_id);
|
||||
|
||||
let audio_bytes = b"fake audio content for test";
|
||||
let filename = "2026-04-13T10-30-00Z.m4a";
|
||||
@@ -55,28 +37,15 @@ async fn web_audio_serves_file() {
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
assert_eq!(
|
||||
response
|
||||
.headers()
|
||||
.get("content-type")
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
"audio/mp4"
|
||||
);
|
||||
assert_eq!(header_opt(&response, "content-type"), Some("audio/mp4"));
|
||||
|
||||
let bytes = axum::body::to_bytes(response.into_body(), usize::MAX)
|
||||
.await
|
||||
.unwrap();
|
||||
let bytes = common::body_bytes(response).await;
|
||||
assert_eq!(&bytes[..], audio_bytes);
|
||||
|
||||
let _ = std::fs::remove_dir_all(&data_path);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn web_audio_path_traversal_rejected() {
|
||||
let config = test_config();
|
||||
let app = doctate_server::create_router(config);
|
||||
let app = doctate_server::create_router(test_config());
|
||||
|
||||
let response = app
|
||||
.oneshot(
|
||||
@@ -93,8 +62,7 @@ async fn web_audio_path_traversal_rejected() {
|
||||
|
||||
#[tokio::test]
|
||||
async fn web_audio_invalid_case_id_rejected() {
|
||||
let config = test_config();
|
||||
let app = doctate_server::create_router(config);
|
||||
let app = doctate_server::create_router(test_config());
|
||||
|
||||
let response = app
|
||||
.oneshot(
|
||||
@@ -115,8 +83,7 @@ async fn web_audio_serves_range_as_206() {
|
||||
let data_path = config.data_path.clone();
|
||||
|
||||
let case_id = "770e8400-e29b-41d4-a716-446655440001";
|
||||
let case_dir = data_path.join("dr_test").join(case_id);
|
||||
std::fs::create_dir_all(&case_dir).unwrap();
|
||||
let case_dir = common::seed_case(&data_path, "dr_test", case_id);
|
||||
|
||||
let audio_bytes: Vec<u8> = (0u8..=200u8).collect();
|
||||
let filename = "2026-04-13T10-30-00Z.m4a";
|
||||
@@ -136,39 +103,14 @@ async fn web_audio_serves_range_as_206() {
|
||||
|
||||
assert_eq!(response.status(), StatusCode::PARTIAL_CONTENT);
|
||||
assert_eq!(
|
||||
response
|
||||
.headers()
|
||||
.get("content-range")
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
format!("bytes 10-19/{}", audio_bytes.len())
|
||||
);
|
||||
assert_eq!(
|
||||
response
|
||||
.headers()
|
||||
.get("content-length")
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
"10"
|
||||
);
|
||||
assert_eq!(
|
||||
response
|
||||
.headers()
|
||||
.get("accept-ranges")
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
"bytes"
|
||||
header_opt(&response, "content-range"),
|
||||
Some(format!("bytes 10-19/{}", audio_bytes.len()).as_str())
|
||||
);
|
||||
assert_eq!(header_opt(&response, "content-length"), Some("10"));
|
||||
assert_eq!(header_opt(&response, "accept-ranges"), Some("bytes"));
|
||||
|
||||
let bytes = axum::body::to_bytes(response.into_body(), usize::MAX)
|
||||
.await
|
||||
.unwrap();
|
||||
let bytes = common::body_bytes(response).await;
|
||||
assert_eq!(&bytes[..], &audio_bytes[10..20]);
|
||||
|
||||
let _ = std::fs::remove_dir_all(&data_path);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -177,8 +119,7 @@ async fn web_audio_invalid_range_returns_416() {
|
||||
let data_path = config.data_path.clone();
|
||||
|
||||
let case_id = "770e8400-e29b-41d4-a716-446655440002";
|
||||
let case_dir = data_path.join("dr_test").join(case_id);
|
||||
std::fs::create_dir_all(&case_dir).unwrap();
|
||||
let case_dir = common::seed_case(&data_path, "dr_test", case_id);
|
||||
|
||||
let audio_bytes = b"short";
|
||||
let filename = "2026-04-13T10-30-00Z.m4a";
|
||||
@@ -198,16 +139,9 @@ async fn web_audio_invalid_range_returns_416() {
|
||||
|
||||
assert_eq!(response.status(), StatusCode::RANGE_NOT_SATISFIABLE);
|
||||
assert_eq!(
|
||||
response
|
||||
.headers()
|
||||
.get("content-range")
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
format!("bytes */{}", audio_bytes.len())
|
||||
header_opt(&response, "content-range"),
|
||||
Some(format!("bytes */{}", audio_bytes.len()).as_str())
|
||||
);
|
||||
|
||||
let _ = std::fs::remove_dir_all(&data_path);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -216,8 +150,7 @@ async fn web_audio_no_range_header_advertises_accept_ranges() {
|
||||
let data_path = config.data_path.clone();
|
||||
|
||||
let case_id = "770e8400-e29b-41d4-a716-446655440003";
|
||||
let case_dir = data_path.join("dr_test").join(case_id);
|
||||
std::fs::create_dir_all(&case_dir).unwrap();
|
||||
let case_dir = common::seed_case(&data_path, "dr_test", case_id);
|
||||
|
||||
let audio_bytes = b"full file content";
|
||||
let filename = "2026-04-13T10-30-00Z.m4a";
|
||||
@@ -235,32 +168,16 @@ async fn web_audio_no_range_header_advertises_accept_ranges() {
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
assert_eq!(header_opt(&response, "accept-ranges"), Some("bytes"));
|
||||
assert_eq!(
|
||||
response
|
||||
.headers()
|
||||
.get("accept-ranges")
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
"bytes"
|
||||
header_opt(&response, "content-length"),
|
||||
Some(audio_bytes.len().to_string().as_str())
|
||||
);
|
||||
assert_eq!(
|
||||
response
|
||||
.headers()
|
||||
.get("content-length")
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
audio_bytes.len().to_string()
|
||||
);
|
||||
|
||||
let _ = std::fs::remove_dir_all(&data_path);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn web_audio_nonexistent_file_returns_404() {
|
||||
let config = test_config();
|
||||
let app = doctate_server::create_router(config);
|
||||
let app = doctate_server::create_router(test_config());
|
||||
|
||||
let response = app
|
||||
.oneshot(
|
||||
|
||||
Reference in New Issue
Block a user