mirror of
https://github.com/RaisFast/raisfast.git
synced 2026-09-24 16:02:44 +00:00
225 lines
6.8 KiB
Rust
225 lines
6.8 KiB
Rust
use super::*;
|
|
|
|
async fn setup_with_post() -> (axum::Router, AppState, String, String) {
|
|
let (mut app, state) = test_app().await;
|
|
let (int_id, doc_id) = create_author(&state.pool).await;
|
|
let tok = make_token(&doc_id, int_id, raisfast::models::user::UserRole::Author);
|
|
let slug = create_published_post(&mut app, &tok).await;
|
|
(app, state, tok, slug)
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn guest_comment_success() {
|
|
let (mut app, _, _, slug) = setup_with_post().await;
|
|
let (status, body): (StatusCode, Value) = send(
|
|
&mut app,
|
|
post_json(
|
|
&format!("/api/v1/posts/{slug}/comments"),
|
|
json!({"content": "Nice!", "nickname": "Guest1", "email": "g@test.com"}),
|
|
),
|
|
)
|
|
.await;
|
|
assert!(status.is_success(), "{status} {body:?}");
|
|
assert_eq!(body["data"]["content"], "Nice!");
|
|
assert_eq!(body["data"]["nickname"], "Guest1");
|
|
assert!(body["data"]["created_by"].is_null());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn guest_comment_requires_nickname() {
|
|
let (mut app, _, _, slug) = setup_with_post().await;
|
|
let (status, body): (StatusCode, Value) = send(
|
|
&mut app,
|
|
post_json(
|
|
&format!("/api/v1/posts/{slug}/comments"),
|
|
json!({"content": "no nick"}),
|
|
),
|
|
)
|
|
.await;
|
|
assert_eq!(status, StatusCode::BAD_REQUEST);
|
|
assert_eq!(body["code"], 40000);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn authed_comment_success() {
|
|
let (mut app, _, _, slug) = setup_with_post().await;
|
|
let (tok, _) = register_and_login(&mut app, "cmtr@test.com", "cmtr", "Password123").await;
|
|
let (status, body): (StatusCode, Value) = send(
|
|
&mut app,
|
|
post_json_auth(
|
|
&format!("/api/v1/posts/{slug}/comments/authed"),
|
|
json!({"content": "Auth comment"}),
|
|
&tok,
|
|
),
|
|
)
|
|
.await;
|
|
assert!(status.is_success(), "{status} {body:?}");
|
|
assert_eq!(body["data"]["content"], "Auth comment");
|
|
assert!(body["data"]["created_by"].is_number());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn nested_comment() {
|
|
let (mut app, state, _, slug) = setup_with_post().await;
|
|
let (_, b1): (StatusCode, Value) = send(
|
|
&mut app,
|
|
post_json(
|
|
&format!("/api/v1/posts/{slug}/comments"),
|
|
json!({"content": "Parent", "nickname": "G1"}),
|
|
),
|
|
)
|
|
.await;
|
|
let pid = b1["data"]["id"].as_i64().unwrap();
|
|
|
|
let approve_sql = format!(
|
|
"UPDATE comments SET status = 'approved' WHERE id = {}",
|
|
raisfast::db::dialect::ph(1)
|
|
);
|
|
sqlx::query(&approve_sql)
|
|
.bind(pid)
|
|
.execute(&state.pool)
|
|
.await
|
|
.unwrap();
|
|
|
|
let (status, body): (StatusCode, Value) = send(
|
|
&mut app,
|
|
post_json(
|
|
&format!("/api/v1/posts/{slug}/comments"),
|
|
json!({"content": "Reply", "nickname": "G2", "parent_id": pid.to_string()}),
|
|
),
|
|
)
|
|
.await;
|
|
assert!(status.is_success(), "{status} {body:?}");
|
|
assert_eq!(body["data"]["parent_id"], pid);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn list_comments() {
|
|
let (mut app, state, _, slug) = setup_with_post().await;
|
|
let _: (StatusCode, Value) = send(
|
|
&mut app,
|
|
post_json(
|
|
&format!("/api/v1/posts/{slug}/comments"),
|
|
json!({"content": "C1", "nickname": "A"}),
|
|
),
|
|
)
|
|
.await;
|
|
let _: (StatusCode, Value) = send(
|
|
&mut app,
|
|
post_json(
|
|
&format!("/api/v1/posts/{slug}/comments"),
|
|
json!({"content": "C2", "nickname": "B"}),
|
|
),
|
|
)
|
|
.await;
|
|
|
|
sqlx::query("UPDATE comments SET status = 'approved' WHERE status = 'pending'")
|
|
.execute(&state.pool)
|
|
.await
|
|
.unwrap();
|
|
|
|
let (status, body): (StatusCode, Value) =
|
|
send(&mut app, get_req(&format!("/api/v1/posts/{slug}/comments"))).await;
|
|
assert!(status.is_success());
|
|
let items = body["data"]["items"].as_array().unwrap();
|
|
assert!(items.len() >= 2);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn delete_own_comment() {
|
|
let (mut app, _, _, slug) = setup_with_post().await;
|
|
let (tok, _) = register_and_login(&mut app, "delc@test.com", "delcuser", "Password123").await;
|
|
let (_, b): (StatusCode, Value) = send(
|
|
&mut app,
|
|
post_json_auth(
|
|
&format!("/api/v1/posts/{slug}/comments/authed"),
|
|
json!({"content": "mine"}),
|
|
&tok,
|
|
),
|
|
)
|
|
.await;
|
|
let cid = b["data"]["document_id"].as_str().unwrap().to_string();
|
|
let (status, _): (StatusCode, Value) = send(
|
|
&mut app,
|
|
delete_auth(&format!("/api/v1/comments/{cid}"), &tok),
|
|
)
|
|
.await;
|
|
assert!(status.is_success());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn delete_not_owner_forbidden() {
|
|
let (mut app, _, _, slug) = setup_with_post().await;
|
|
let (t1, _) = register_and_login(&mut app, "own@test.com", "own", "Password123").await;
|
|
let (t2, _) = register_and_login(&mut app, "str@test.com", "str", "Password123").await;
|
|
let (_, b): (StatusCode, Value) = send(
|
|
&mut app,
|
|
post_json_auth(
|
|
&format!("/api/v1/posts/{slug}/comments/authed"),
|
|
json!({"content": "x"}),
|
|
&t1,
|
|
),
|
|
)
|
|
.await;
|
|
let cid = b["data"]["document_id"].as_str().unwrap().to_string();
|
|
let (status, _): (StatusCode, Value) = send(
|
|
&mut app,
|
|
delete_auth(&format!("/api/v1/comments/{cid}"), &t2),
|
|
)
|
|
.await;
|
|
assert_eq!(status, StatusCode::FORBIDDEN);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn update_status_admin() {
|
|
let (mut app, state, _, slug) = setup_with_post().await;
|
|
let _: (StatusCode, Value) = send(
|
|
&mut app,
|
|
post_json(
|
|
&format!("/api/v1/posts/{slug}/comments"),
|
|
json!({"content": "mod me", "nickname": "G"}),
|
|
),
|
|
)
|
|
.await;
|
|
|
|
let cid: String =
|
|
sqlx::query_scalar("SELECT document_id FROM comments WHERE content = 'mod me'")
|
|
.fetch_one(&state.pool)
|
|
.await
|
|
.unwrap();
|
|
|
|
let (admin_int_id, admin_doc_id) = create_admin(&state.pool).await;
|
|
let admin_tok = make_token(
|
|
&admin_doc_id,
|
|
admin_int_id,
|
|
raisfast::models::user::UserRole::Admin,
|
|
);
|
|
let (status, _): (StatusCode, Value) = send(
|
|
&mut app,
|
|
put_json_auth(
|
|
&format!("/api/v1/comments/{cid}/status"),
|
|
json!({"status": "approved"}),
|
|
&admin_tok,
|
|
),
|
|
)
|
|
.await;
|
|
assert!(status.is_success());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn update_status_requires_admin() {
|
|
let (mut app, _, _, _) = setup_with_post().await;
|
|
let (tok, _) = register_and_login(&mut app, "na@test.com", "nauser", "Password123").await;
|
|
let fake = "nonexistent-document-id";
|
|
let (status, _): (StatusCode, Value) = send(
|
|
&mut app,
|
|
put_json_auth(
|
|
&format!("/api/v1/comments/{fake}/status"),
|
|
json!({"status": "approved"}),
|
|
&tok,
|
|
),
|
|
)
|
|
.await;
|
|
assert_eq!(status, StatusCode::FORBIDDEN);
|
|
}
|