use serde::Deserialize; use serde_json::Value; use crate::errors::AppError; #[derive(Debug)] pub enum WebhookType { Review(ReviewPayload), } #[derive(Deserialize, Debug)] pub struct ReviewPayload { pub action: String, pub pull_request: PullRequest, pub comment: Comment, } #[derive(Deserialize, Debug)] pub struct PullRequest { pub id: u64, } #[derive(Deserialize, Debug)] pub struct Comment { pub id: u64, pub body: String, pub user: User, } #[derive(Deserialize, Debug)] pub struct User { pub id: u64, } impl WebhookType { pub fn from_event(event: &str, json: Value) -> Result { match event { "pull_request_comment" => Ok(WebhookType::Review(serde_json::from_value(json)?)), _ => Err(AppError::UnknownEventErr), } } } #[cfg(test)] mod tests { use super::*; use serde_json::json; #[test] fn test_from_event_valid_pull_request_comment() { let json = json!({ "action": "created", "pull_request": { "id": 42 }, "comment": { "id": 7, "body": "LGTM", "user": { "id": 100 } } }); let result = WebhookType::from_event("pull_request_comment", json); assert!(result.is_ok()); match result.unwrap() { WebhookType::Review(payload) => { assert_eq!(payload.action, "created"); assert_eq!(payload.pull_request.id, 42); assert_eq!(payload.comment.id, 7); assert_eq!(payload.comment.body, "LGTM"); assert_eq!(payload.comment.user.id, 100); } } } #[test] fn test_from_event_unknown_event() { let json = json!({}); let result = WebhookType::from_event("push", json); assert!(result.is_err()); match result.unwrap_err() { AppError::UnknownEventErr => {} _ => panic!("expected UnknownEventErr"), } } #[test] fn test_from_event_malformed_json() { let json = json!({ "action": "created" // pull_request and comment are missing }); let result = WebhookType::from_event("pull_request_comment", json); assert!(result.is_err()); match result.unwrap_err() { AppError::BadJsonStructErr(_) => {} _ => panic!("expected BadJsonStructErr"), } } #[test] fn test_deserialize_review_payload() { let json = json!({ "action": "edited", "pull_request": { "id": 99 }, "comment": { "id": 12, "body": "Needs work", "user": { "id": 200 } } }); let payload: ReviewPayload = serde_json::from_value(json).unwrap(); assert_eq!(payload.action, "edited"); assert_eq!(payload.pull_request.id, 99); assert_eq!(payload.comment.id, 12); assert_eq!(payload.comment.body, "Needs work"); assert_eq!(payload.comment.user.id, 200); } #[test] fn test_from_event_empty_json() { let result = WebhookType::from_event("pull_request_comment", json!({})); assert!(result.is_err()); assert!(matches!(result.unwrap_err(), AppError::BadJsonStructErr(_))); } }