Files
readur/tests/integration_ocr_language_endpoints.rs

386 lines
14 KiB
Rust

use readur::test_utils::TestContext;
use axum::http::StatusCode;
use axum::body::Body;
use axum::http::Request;
use tower::ServiceExt;
use serde_json::json;
use tempfile::TempDir;
use std::fs;
use uuid::Uuid;
#[tokio::test]
async fn test_get_available_languages_success() {
// Create temporary directory for tessdata
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let tessdata_path = temp_dir.path().join("tessdata");
fs::create_dir_all(&tessdata_path).expect("Failed to create tessdata directory");
// Create mock language files
let language_files = vec![
"eng.traineddata",
"spa.traineddata",
"fra.traineddata",
"deu.traineddata",
"ita.traineddata",
"por.traineddata",
];
for file in language_files {
fs::write(tessdata_path.join(file), "mock language data")
.expect("Failed to create mock language file");
}
// Set environment variable for tessdata path
std::env::set_var("TESSDATA_PREFIX", &tessdata_path);
let ctx = TestContext::new().await;
// Create test user and get token
let auth_helper = readur::test_utils::TestAuthHelper::new(ctx.app().clone());
let mut test_user = auth_helper.create_test_user().await;
let user_id = test_user.user_response.id;
let token = test_user.login(&auth_helper).await.unwrap();
// Create user settings
sqlx::query(
"INSERT INTO settings (user_id, ocr_language) VALUES ($1, $2)
ON CONFLICT (user_id) DO UPDATE SET ocr_language = $2"
)
.bind(user_id)
.bind("eng")
.execute(&ctx.state().db.pool)
.await
.expect("Failed to create user settings");
let request = Request::builder()
.method("GET")
.uri("/api/ocr/languages")
.header("Authorization", format!("Bearer {}", token))
.body(Body::empty())
.unwrap();
let response = ctx.app().clone().oneshot(request).await.unwrap();
assert_eq!(response.status(), StatusCode::OK);
let body_bytes = axum::body::to_bytes(response.into_body(), usize::MAX).await.unwrap();
let body: serde_json::Value = serde_json::from_slice(&body_bytes).unwrap();
assert!(body.get("available_languages").is_some());
let languages = body["available_languages"].as_array().unwrap();
assert!(languages.len() >= 6); // We created 6 mock languages
// Check that languages have the expected structure
for lang in languages {
assert!(lang.get("code").is_some());
assert!(lang.get("name").is_some());
}
// Check that English is included
let has_english = languages.iter().any(|lang| {
lang.get("code").unwrap().as_str().unwrap() == "eng"
});
assert!(has_english);
}
#[tokio::test]
async fn test_get_available_languages_unauthorized() {
// Create temporary directory for tessdata
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let tessdata_path = temp_dir.path().join("tessdata");
fs::create_dir_all(&tessdata_path).expect("Failed to create tessdata directory");
// Create mock language files
fs::write(tessdata_path.join("eng.traineddata"), "mock").unwrap();
std::env::set_var("TESSDATA_PREFIX", &tessdata_path);
let ctx = TestContext::new().await;
let request = Request::builder()
.method("GET")
.uri("/api/ocr/languages")
.body(Body::empty())
.unwrap();
let response = ctx.app().clone().oneshot(request).await.unwrap();
assert_eq!(response.status(), StatusCode::UNAUTHORIZED);
}
#[tokio::test]
async fn test_retry_ocr_with_language_success() {
// Create temporary directory for tessdata
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let tessdata_path = temp_dir.path().join("tessdata");
fs::create_dir_all(&tessdata_path).expect("Failed to create tessdata directory");
// Create mock language files
fs::write(tessdata_path.join("eng.traineddata"), "mock").unwrap();
fs::write(tessdata_path.join("spa.traineddata"), "mock").unwrap();
std::env::set_var("TESSDATA_PREFIX", &tessdata_path);
let ctx = TestContext::new().await;
// Create test user and get token
let auth_helper = readur::test_utils::TestAuthHelper::new(ctx.app().clone());
let mut test_user = auth_helper.create_test_user().await;
let user_id = test_user.user_response.id;
let token = test_user.login(&auth_helper).await.unwrap();
// Create a test document
let document_id = Uuid::new_v4();
sqlx::query(
"INSERT INTO documents (id, user_id, filename, original_filename, file_size, mime_type, ocr_status, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5, $6, $7, NOW(), NOW())"
)
.bind(document_id)
.bind(user_id)
.bind("test.pdf")
.bind("test.pdf")
.bind(1024i64)
.bind("application/pdf")
.bind("failed")
.execute(&ctx.state().db.pool)
.await
.expect("Failed to create test document");
let retry_request = json!({
"language": "spa"
});
let request = Request::builder()
.method("POST")
.uri(&format!("/api/documents/{}/retry-ocr", document_id))
.header("Authorization", format!("Bearer {}", token))
.header("Content-Type", "application/json")
.body(Body::from(serde_json::to_vec(&retry_request).unwrap()))
.unwrap();
let response = ctx.app().clone().oneshot(request).await.unwrap();
assert_eq!(response.status(), StatusCode::OK);
let body_bytes = axum::body::to_bytes(response.into_body(), usize::MAX).await.unwrap();
let body: serde_json::Value = serde_json::from_slice(&body_bytes).unwrap();
assert_eq!(body["success"].as_bool().unwrap(), true);
assert!(body.get("message").is_some());
}
#[tokio::test]
async fn test_retry_ocr_with_invalid_language() {
// Create temporary directory for tessdata
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let tessdata_path = temp_dir.path().join("tessdata");
fs::create_dir_all(&tessdata_path).expect("Failed to create tessdata directory");
// Create mock language files
fs::write(tessdata_path.join("eng.traineddata"), "mock").unwrap();
std::env::set_var("TESSDATA_PREFIX", &tessdata_path);
let ctx = TestContext::new().await;
// Create test user and get token
let auth_helper = readur::test_utils::TestAuthHelper::new(ctx.app().clone());
let mut test_user = auth_helper.create_test_user().await;
let user_id = test_user.user_response.id;
let token = test_user.login(&auth_helper).await.unwrap();
// Create a test document
let document_id = Uuid::new_v4();
sqlx::query(
"INSERT INTO documents (id, user_id, filename, original_filename, file_size, mime_type, ocr_status, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5, $6, $7, NOW(), NOW())"
)
.bind(document_id)
.bind(user_id)
.bind("test.pdf")
.bind("test.pdf")
.bind(1024i64)
.bind("application/pdf")
.bind("failed")
.execute(&ctx.state().db.pool)
.await
.expect("Failed to create test document");
let retry_request = json!({
"language": "invalid_lang"
});
let request = Request::builder()
.method("POST")
.uri(&format!("/api/documents/{}/retry-ocr", document_id))
.header("Authorization", format!("Bearer {}", token))
.header("Content-Type", "application/json")
.body(Body::from(serde_json::to_vec(&retry_request).unwrap()))
.unwrap();
let response = ctx.app().clone().oneshot(request).await.unwrap();
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
}
#[tokio::test]
async fn test_retry_ocr_with_multiple_languages_success() {
// Create temporary directory for tessdata
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let tessdata_path = temp_dir.path().join("tessdata");
fs::create_dir_all(&tessdata_path).expect("Failed to create tessdata directory");
// Create mock language files
fs::write(tessdata_path.join("eng.traineddata"), "mock").unwrap();
fs::write(tessdata_path.join("spa.traineddata"), "mock").unwrap();
fs::write(tessdata_path.join("fra.traineddata"), "mock").unwrap();
std::env::set_var("TESSDATA_PREFIX", &tessdata_path);
let ctx = TestContext::new().await;
// Create test user and get token
let auth_helper = readur::test_utils::TestAuthHelper::new(ctx.app().clone());
let mut test_user = auth_helper.create_test_user().await;
let user_id = test_user.user_response.id;
let token = test_user.login(&auth_helper).await.unwrap();
// Create a test document
let document_id = Uuid::new_v4();
sqlx::query(
"INSERT INTO documents (id, user_id, filename, original_filename, file_size, mime_type, ocr_status, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5, $6, $7, NOW(), NOW())"
)
.bind(document_id)
.bind(user_id)
.bind("test.pdf")
.bind("test.pdf")
.bind(1024i64)
.bind("application/pdf")
.bind("failed")
.execute(&ctx.state().db.pool)
.await
.expect("Failed to create test document");
let retry_request = json!({
"languages": ["eng", "spa", "fra"]
});
let request = Request::builder()
.method("POST")
.uri(&format!("/api/documents/{}/retry-ocr", document_id))
.header("Authorization", format!("Bearer {}", token))
.header("Content-Type", "application/json")
.body(Body::from(serde_json::to_vec(&retry_request).unwrap()))
.unwrap();
let response = ctx.app().clone().oneshot(request).await.unwrap();
assert_eq!(response.status(), StatusCode::OK);
let body_bytes = axum::body::to_bytes(response.into_body(), usize::MAX).await.unwrap();
let body: serde_json::Value = serde_json::from_slice(&body_bytes).unwrap();
assert_eq!(body["success"].as_bool().unwrap(), true);
assert!(body.get("message").is_some());
}
#[tokio::test]
async fn test_retry_ocr_with_too_many_languages() {
// Create temporary directory for tessdata
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let tessdata_path = temp_dir.path().join("tessdata");
fs::create_dir_all(&tessdata_path).expect("Failed to create tessdata directory");
// Create mock language files
fs::write(tessdata_path.join("eng.traineddata"), "mock").unwrap();
fs::write(tessdata_path.join("spa.traineddata"), "mock").unwrap();
fs::write(tessdata_path.join("fra.traineddata"), "mock").unwrap();
fs::write(tessdata_path.join("deu.traineddata"), "mock").unwrap();
fs::write(tessdata_path.join("ita.traineddata"), "mock").unwrap();
std::env::set_var("TESSDATA_PREFIX", &tessdata_path);
let ctx = TestContext::new().await;
// Create test user and get token
let auth_helper = readur::test_utils::TestAuthHelper::new(ctx.app().clone());
let mut test_user = auth_helper.create_test_user().await;
let user_id = test_user.user_response.id;
let token = test_user.login(&auth_helper).await.unwrap();
// Create a test document
let document_id = Uuid::new_v4();
sqlx::query(
"INSERT INTO documents (id, user_id, filename, original_filename, file_size, mime_type, ocr_status, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5, $6, $7, NOW(), NOW())"
)
.bind(document_id)
.bind(user_id)
.bind("test.pdf")
.bind("test.pdf")
.bind(1024i64)
.bind("application/pdf")
.bind("failed")
.execute(&ctx.state().db.pool)
.await
.expect("Failed to create test document");
// Try to use more than 4 languages (should fail)
let retry_request = json!({
"languages": ["eng", "spa", "fra", "deu", "ita"]
});
let request = Request::builder()
.method("POST")
.uri(&format!("/api/documents/{}/retry-ocr", document_id))
.header("Authorization", format!("Bearer {}", token))
.header("Content-Type", "application/json")
.body(Body::from(serde_json::to_vec(&retry_request).unwrap()))
.unwrap();
let response = ctx.app().clone().oneshot(request).await.unwrap();
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
}
#[tokio::test]
async fn test_retry_ocr_with_invalid_language_in_array() {
// Create temporary directory for tessdata
let temp_dir = TempDir::new().expect("Failed to create temp directory");
let tessdata_path = temp_dir.path().join("tessdata");
fs::create_dir_all(&tessdata_path).expect("Failed to create tessdata directory");
// Create mock language files
fs::write(tessdata_path.join("eng.traineddata"), "mock").unwrap();
fs::write(tessdata_path.join("spa.traineddata"), "mock").unwrap();
std::env::set_var("TESSDATA_PREFIX", &tessdata_path);
let ctx = TestContext::new().await;
// Create test user and get token
let auth_helper = readur::test_utils::TestAuthHelper::new(ctx.app().clone());
let mut test_user = auth_helper.create_test_user().await;
let user_id = test_user.user_response.id;
let token = test_user.login(&auth_helper).await.unwrap();
// Create a test document
let document_id = Uuid::new_v4();
sqlx::query(
"INSERT INTO documents (id, user_id, filename, original_filename, file_size, mime_type, ocr_status, created_at, updated_at)
VALUES ($1, $2, $3, $4, $5, $6, $7, NOW(), NOW())"
)
.bind(document_id)
.bind(user_id)
.bind("test.pdf")
.bind("test.pdf")
.bind(1024i64)
.bind("application/pdf")
.bind("failed")
.execute(&ctx.state().db.pool)
.await
.expect("Failed to create test document");
// Include an invalid language in the array
let retry_request = json!({
"languages": ["eng", "spa", "invalid_lang"]
});
let request = Request::builder()
.method("POST")
.uri(&format!("/api/documents/{}/retry-ocr", document_id))
.header("Authorization", format!("Bearer {}", token))
.header("Content-Type", "application/json")
.body(Body::from(serde_json::to_vec(&retry_request).unwrap()))
.unwrap();
let response = ctx.app().clone().oneshot(request).await.unwrap();
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
}