add test + json errors

This commit is contained in:
2026-05-31 21:30:17 +00:00
parent 227fcfaafb
commit 7e3b49ad76
3 changed files with 231 additions and 24 deletions
+160 -7
View File
@@ -1,8 +1,8 @@
use anyhow::anyhow;
use serde_json::Value;
use crate::errors::AppError;
#[derive(Debug, PartialEq)]
pub enum WebhookType {
Review(u64, String),
}
@@ -15,9 +15,9 @@ impl TryFrom<Value> for WebhookType {
let comment = json.get("comment");
let action = json
.get("action")
.ok_or(anyhow!("action not found"))?
.ok_or(AppError::MissingField("action".into()))?
.as_str()
.ok_or(anyhow!("error while action"))?;
.ok_or(AppError::WrongFieldType("action".into()))?;
if action != "created" {
return Err(AppError::BadJsonStructErr);
@@ -26,16 +26,16 @@ impl TryFrom<Value> for WebhookType {
if let (Some(pull_request), Some(comment)) = (pull_request, comment) {
let comment_body = comment
.get("body")
.ok_or(anyhow!("comment body not found"))?
.ok_or(AppError::MissingField("comment.body".into()))?
.as_str()
.ok_or(anyhow!("error while get pr comment"))?
.ok_or(AppError::WrongFieldType("comment.body".into()))?
.to_string();
let pr_id = pull_request
.get("id")
.ok_or(anyhow!("pr id not found"))?
.ok_or(AppError::MissingField("pull_request.id".into()))?
.as_u64()
.ok_or(anyhow!("error while get pr id"))?;
.ok_or(AppError::WrongFieldType("pull_request.id".into()))?;
return Ok(WebhookType::Review(pr_id, comment_body));
}
@@ -43,3 +43,156 @@ impl TryFrom<Value> for WebhookType {
Err(AppError::BadJsonStructErr)
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn valid_webhook_parses_review() {
let payload = json!({
"action": "created",
"pull_request": { "id": 42 },
"comment": { "body": "LGTM" }
});
let result = WebhookType::try_from(payload).unwrap();
assert_eq!(result, WebhookType::Review(42, "LGTM".into()));
}
#[test]
fn missing_action_returns_error() {
let payload = json!({
"pull_request": { "id": 1 },
"comment": { "body": "ok" }
});
let err = WebhookType::try_from(payload).unwrap_err();
assert!(matches!(err, AppError::MissingField(ref f) if f == "action"));
}
#[test]
fn action_not_created_returns_bad_json_struct() {
let payload = json!({
"action": "updated",
"pull_request": { "id": 1 },
"comment": { "body": "ok" }
});
let err = WebhookType::try_from(payload).unwrap_err();
assert!(matches!(err, AppError::BadJsonStructErr));
}
#[test]
fn action_not_a_string_returns_error() {
let payload = json!({
"action": 123,
"pull_request": { "id": 1 },
"comment": { "body": "ok" }
});
let err = WebhookType::try_from(payload).unwrap_err();
assert!(matches!(err, AppError::WrongFieldType(ref f) if f == "action"));
}
#[test]
fn missing_pull_request_returns_bad_json_struct() {
let payload = json!({
"action": "created",
"comment": { "body": "ok" }
});
let err = WebhookType::try_from(payload).unwrap_err();
assert!(matches!(err, AppError::BadJsonStructErr));
}
#[test]
fn missing_comment_returns_bad_json_struct() {
let payload = json!({
"action": "created",
"pull_request": { "id": 1 }
});
let err = WebhookType::try_from(payload).unwrap_err();
assert!(matches!(err, AppError::BadJsonStructErr));
}
#[test]
fn missing_pr_id_returns_error() {
let payload = json!({
"action": "created",
"pull_request": { "number": 1 },
"comment": { "body": "ok" }
});
let err = WebhookType::try_from(payload).unwrap_err();
assert!(matches!(err, AppError::MissingField(ref f) if f == "pull_request.id"));
}
#[test]
fn pr_id_not_a_number_returns_error() {
let payload = json!({
"action": "created",
"pull_request": { "id": "not-a-number" },
"comment": { "body": "ok" }
});
let err = WebhookType::try_from(payload).unwrap_err();
assert!(matches!(err, AppError::WrongFieldType(ref f) if f == "pull_request.id"));
}
#[test]
fn missing_comment_body_returns_error() {
let payload = json!({
"action": "created",
"pull_request": { "id": 1 },
"comment": { "text": "no body" }
});
let err = WebhookType::try_from(payload).unwrap_err();
assert!(matches!(err, AppError::MissingField(ref f) if f == "comment.body"));
}
#[test]
fn comment_body_not_a_string_returns_error() {
let payload = json!({
"action": "created",
"pull_request": { "id": 1 },
"comment": { "body": 999 }
});
let err = WebhookType::try_from(payload).unwrap_err();
assert!(matches!(err, AppError::WrongFieldType(ref f) if f == "comment.body"));
}
#[test]
fn null_pull_request_returns_error() {
let payload = json!({
"action": "created",
"pull_request": null,
"comment": { "body": "ok" }
});
let err = WebhookType::try_from(payload).unwrap_err();
assert!(matches!(err, AppError::MissingField(ref f) if f == "pull_request.id"));
}
#[test]
fn null_comment_returns_error() {
let payload = json!({
"action": "created",
"pull_request": { "id": 1 },
"comment": null
});
let err = WebhookType::try_from(payload).unwrap_err();
assert!(matches!(err, AppError::MissingField(ref f) if f == "comment.body"));
}
#[test]
fn large_pr_id_parses_correctly() {
let payload = json!({
"action": "created",
"pull_request": { "id": 18446744073709551615u64 },
"comment": { "body": "max u64" }
});
let result = WebhookType::try_from(payload).unwrap();
assert_eq!(result, WebhookType::Review(18446744073709551615, "max u64".into()));
}
#[test]
fn full_webhook_payload_parses() {
let payload: Value = serde_json::from_str(include_str!("../docs/webhook_pr_body.json")).unwrap();
let result = WebhookType::try_from(payload).unwrap();
assert_eq!(result, WebhookType::Review(1, "Test comment".into()));
}
}