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.
189 lines
5.6 KiB
Rust
189 lines
5.6 KiB
Rust
//! Integration tests for the `PUT /api/v1/sources/preferred` endpoint.
|
|
//!
|
|
//! Tests:
|
|
//! - Setting preferred sources
|
|
//! - Clearing all preferred sources
|
|
//! - Authentication requirement
|
|
//!
|
|
//! 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()
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn update_preferred_sets_sources() {
|
|
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("pref-set@example.com")
|
|
.await;
|
|
|
|
// Create a theme first
|
|
let theme_body = serde_json::json!({
|
|
"name": "Pref Theme",
|
|
"theme": "Test",
|
|
"categories": ["Cat"]
|
|
});
|
|
let (theme_status, theme_resp) = app
|
|
.post_with_session("/api/v1/themes", &theme_body, &session)
|
|
.await;
|
|
assert_eq!(theme_status, StatusCode::CREATED);
|
|
let theme_id = theme_resp["id"].as_str().unwrap();
|
|
|
|
// Create 3 sources
|
|
let mut source_ids = Vec::new();
|
|
for i in 1..=3 {
|
|
let body = serde_json::json!({
|
|
"title": format!("Source {}", i),
|
|
"url": format!("https://source{}.example.com", i),
|
|
"theme_id": theme_id
|
|
});
|
|
let (status, resp) = app
|
|
.post_with_session("/api/v1/sources", &body, &session)
|
|
.await;
|
|
assert_eq!(status, StatusCode::CREATED);
|
|
source_ids.push(resp["id"].as_str().unwrap().to_string());
|
|
}
|
|
|
|
// PUT /sources/preferred with [id1, id3]
|
|
let pref_body = serde_json::json!({
|
|
"source_ids": [source_ids[0], source_ids[2]],
|
|
"theme_id": theme_id
|
|
});
|
|
let (pref_status, _) = app
|
|
.put_with_session("/api/v1/sources/preferred", &pref_body, &session)
|
|
.await;
|
|
assert_eq!(pref_status, StatusCode::NO_CONTENT);
|
|
|
|
// GET /sources → verify preferred flags
|
|
let (list_status, list_body) = app
|
|
.get_with_session(
|
|
&format!("/api/v1/sources?theme_id={}", theme_id),
|
|
&session,
|
|
)
|
|
.await;
|
|
assert_eq!(list_status, StatusCode::OK);
|
|
|
|
let sources = list_body.as_array().expect("Should be an array");
|
|
assert_eq!(sources.len(), 3);
|
|
|
|
for source in sources {
|
|
let id = source["id"].as_str().unwrap();
|
|
let is_preferred = source["is_preferred"].as_bool().unwrap();
|
|
if id == source_ids[0] || id == source_ids[2] {
|
|
assert!(is_preferred, "Source {} should be preferred", id);
|
|
} else {
|
|
assert!(!is_preferred, "Source {} should NOT be preferred", id);
|
|
}
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn update_preferred_clears_all_when_empty() {
|
|
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("pref-clear@example.com")
|
|
.await;
|
|
|
|
// Create a theme
|
|
let theme_body = serde_json::json!({
|
|
"name": "Pref Clear Theme",
|
|
"theme": "Test",
|
|
"categories": ["Cat"]
|
|
});
|
|
let (_, theme_resp) = app
|
|
.post_with_session("/api/v1/themes", &theme_body, &session)
|
|
.await;
|
|
let theme_id = theme_resp["id"].as_str().unwrap();
|
|
|
|
// Create 2 sources
|
|
let mut source_ids = Vec::new();
|
|
for i in 1..=2 {
|
|
let body = serde_json::json!({
|
|
"title": format!("Source {}", i),
|
|
"url": format!("https://clear-source{}.example.com", i),
|
|
"theme_id": theme_id
|
|
});
|
|
let (_, resp) = app
|
|
.post_with_session("/api/v1/sources", &body, &session)
|
|
.await;
|
|
source_ids.push(resp["id"].as_str().unwrap().to_string());
|
|
}
|
|
|
|
// Set some as preferred
|
|
let pref_body = serde_json::json!({
|
|
"source_ids": [source_ids[0]],
|
|
"theme_id": theme_id
|
|
});
|
|
let (pref_status, _) = app
|
|
.put_with_session("/api/v1/sources/preferred", &pref_body, &session)
|
|
.await;
|
|
assert_eq!(pref_status, StatusCode::NO_CONTENT);
|
|
|
|
// Clear all preferred
|
|
let clear_body = serde_json::json!({
|
|
"source_ids": [],
|
|
"theme_id": theme_id
|
|
});
|
|
let (clear_status, _) = app
|
|
.put_with_session("/api/v1/sources/preferred", &clear_body, &session)
|
|
.await;
|
|
assert_eq!(clear_status, StatusCode::OK);
|
|
|
|
// GET /sources → all is_preferred=false
|
|
let (list_status, list_body) = app
|
|
.get_with_session(
|
|
&format!("/api/v1/sources?theme_id={}", theme_id),
|
|
&session,
|
|
)
|
|
.await;
|
|
assert_eq!(list_status, StatusCode::OK);
|
|
|
|
let sources = list_body.as_array().expect("Should be an array");
|
|
for source in sources {
|
|
assert_eq!(
|
|
source["is_preferred"].as_bool().unwrap(),
|
|
false,
|
|
"All sources should be non-preferred after clearing"
|
|
);
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn update_preferred_without_auth_returns_401() {
|
|
if !require_test_db() {
|
|
eprintln!("SKIPPED: TEST_DATABASE_URL not set");
|
|
return;
|
|
}
|
|
|
|
let app = common::TestApp::new().await;
|
|
let body = serde_json::json!({
|
|
"source_ids": [],
|
|
"theme_id": "00000000-0000-0000-0000-000000000000"
|
|
});
|
|
let (status, resp) = app
|
|
.put_with_session("/api/v1/sources/preferred", &body, "invalid-session-token")
|
|
.await;
|
|
|
|
assert_eq!(
|
|
status,
|
|
StatusCode::UNAUTHORIZED,
|
|
"PUT /sources/preferred without auth should return 401"
|
|
);
|
|
assert_eq!(resp["error"], "unauthorized");
|
|
}
|