You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
134 lines
5.0 KiB
Rust
134 lines
5.0 KiB
Rust
//! Integration tests for the article history and provenance endpoints.
|
|
//!
|
|
//! Tests:
|
|
//! - GET /api/v1/article-history — list article history
|
|
//! - DELETE /api/v1/article-history — clear article history
|
|
//! - GET /api/v1/syntheses/:id/provenance — get provenance for a synthesis
|
|
//!
|
|
//! Covers authentication, empty-state responses, and nonexistent lookups.
|
|
//!
|
|
//! Requires a running Postgres instance. Set `TEST_DATABASE_URL` to run.
|
|
|
|
mod common;
|
|
|
|
use axum::http::StatusCode;
|
|
|
|
fn require_test_db() -> bool {
|
|
std::env::var("TEST_DATABASE_URL").is_ok()
|
|
}
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// Authentication
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
#[tokio::test]
|
|
async fn list_article_history_without_auth_returns_401() {
|
|
if !require_test_db() {
|
|
eprintln!("SKIPPED: TEST_DATABASE_URL not set");
|
|
return;
|
|
}
|
|
|
|
let app = common::TestApp::new().await;
|
|
let (status, body) = app
|
|
.get_with_session("/api/v1/article-history", "invalid-token")
|
|
.await;
|
|
|
|
assert_eq!(
|
|
status,
|
|
StatusCode::UNAUTHORIZED,
|
|
"GET /article-history without auth should return 401"
|
|
);
|
|
assert_eq!(body["error"], "unauthorized");
|
|
}
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// List — empty state
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
#[tokio::test]
|
|
async fn list_article_history_returns_empty_initially() {
|
|
if !require_test_db() {
|
|
eprintln!("SKIPPED: TEST_DATABASE_URL not set");
|
|
return;
|
|
}
|
|
|
|
let app = common::TestApp::new().await;
|
|
let (_user_id, session) = app
|
|
.create_authenticated_user("history-empty@example.com")
|
|
.await;
|
|
|
|
let (status, resp) = app
|
|
.get_with_session("/api/v1/article-history", &session)
|
|
.await;
|
|
|
|
assert_eq!(
|
|
status,
|
|
StatusCode::OK,
|
|
"GET /article-history should return 200"
|
|
);
|
|
let items = resp["items"]
|
|
.as_array()
|
|
.expect("Response should contain an items array");
|
|
assert!(items.is_empty(), "New user should have empty article history");
|
|
assert_eq!(resp["total"], 0);
|
|
}
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// Clear history
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
#[tokio::test]
|
|
async fn clear_article_history_returns_200() {
|
|
if !require_test_db() {
|
|
eprintln!("SKIPPED: TEST_DATABASE_URL not set");
|
|
return;
|
|
}
|
|
|
|
let app = common::TestApp::new().await;
|
|
let (_user_id, session) = app
|
|
.create_authenticated_user("history-clear@example.com")
|
|
.await;
|
|
|
|
let (status, resp) = app
|
|
.delete_with_session("/api/v1/article-history", &session)
|
|
.await;
|
|
|
|
assert_eq!(
|
|
status,
|
|
StatusCode::OK,
|
|
"DELETE /article-history should return 200"
|
|
);
|
|
assert_eq!(resp["deleted"], 0, "No entries to delete for a new user");
|
|
}
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// Provenance — nonexistent synthesis
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
#[tokio::test]
|
|
async fn get_provenance_for_nonexistent_synthesis_returns_404() {
|
|
if !require_test_db() {
|
|
eprintln!("SKIPPED: TEST_DATABASE_URL not set");
|
|
return;
|
|
}
|
|
|
|
let app = common::TestApp::new().await;
|
|
let (_user_id, session) = app
|
|
.create_authenticated_user("provenance-404@example.com")
|
|
.await;
|
|
|
|
let random_id = uuid::Uuid::new_v4();
|
|
let (status, _resp) = app
|
|
.get_with_session(
|
|
&format!("/api/v1/syntheses/{}/provenance", random_id),
|
|
&session,
|
|
)
|
|
.await;
|
|
|
|
assert_eq!(
|
|
status,
|
|
StatusCode::NOT_FOUND,
|
|
"GET /syntheses/:id/provenance for nonexistent synthesis should return 404"
|
|
);
|
|
}
|