Skip to main content

octocrab/models/events/payload/
pull_request.rs

1use crate::models::pulls::PullRequest;
2use serde::{Deserialize, Serialize};
3
4/// The payload in a [`super::EventPayload::PullRequestEvent`] type.
5#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
6#[non_exhaustive]
7pub struct PullRequestEventPayload {
8    /// The action this event represents.
9    pub action: PullRequestEventAction,
10    /// The pull request number this event corresponds to.
11    pub number: u64,
12    /// The pull request this event corresponds to.
13    pub pull_request: PullRequest,
14    /// The changes to body or title if this event is of type [`PullRequestEventAction::Edited`].
15    pub changes: Option<PullRequestChanges>,
16}
17
18/// The action on a pull request this event corresponds to.
19#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
20#[serde(rename_all = "snake_case")]
21#[non_exhaustive]
22pub enum PullRequestEventAction {
23    Opened,
24    Closed,
25    Reopened,
26    /// Only available on webhook events.
27    Edited,
28    /// Only available on webhook events.
29    Assigned,
30    /// Only available on webhook events.
31    Unassigned,
32    /// Only available on webhook events.
33    ReviewRequested,
34    /// Only available on webhook events.
35    ReviewRequestRemoved,
36    /// Only available on webhook events.
37    Labeled,
38    /// Only available on webhook events.
39    Unlabeled,
40    /// Only available on webhook events.
41    ///
42    /// This event is fired when the HEAD ref in a pull request is changed.
43    Synchronize,
44}
45
46/// The change which occurred in an event of type [`PullRequestEventAction::Edited`].
47#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
48#[non_exhaustive]
49pub struct PullRequestChanges {
50    pub title: Option<PullRequestEventChangesFrom>,
51    pub body: Option<PullRequestEventChangesFrom>,
52}
53
54/// The previous value of the item (either the body or title) of a pull request which has changed. Only
55/// available in an event of type [`PullRequestEventAction::Edited`].
56#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
57#[serde(rename_all = "lowercase")]
58#[non_exhaustive]
59pub struct PullRequestEventChangesFrom {
60    pub from: String,
61}
62
63#[cfg(test)]
64mod test {
65    use super::{PullRequestChanges, PullRequestEventAction, PullRequestEventChangesFrom};
66    use crate::models::events::{payload::EventPayload, Event};
67    use serde_json::json;
68
69    #[test]
70    fn should_deserialize_action_from_snake_case() {
71        let actions = vec![
72            (r#""opened""#, PullRequestEventAction::Opened),
73            (r#""closed""#, PullRequestEventAction::Closed),
74            (r#""reopened""#, PullRequestEventAction::Reopened),
75            (r#""edited""#, PullRequestEventAction::Edited),
76            (r#""assigned""#, PullRequestEventAction::Assigned),
77            (r#""unassigned""#, PullRequestEventAction::Unassigned),
78            (
79                r#""review_requested""#,
80                PullRequestEventAction::ReviewRequested,
81            ),
82            (
83                r#""review_request_removed""#,
84                PullRequestEventAction::ReviewRequestRemoved,
85            ),
86            (r#""labeled""#, PullRequestEventAction::Labeled),
87            (r#""unlabeled""#, PullRequestEventAction::Unlabeled),
88            (r#""synchronize""#, PullRequestEventAction::Synchronize),
89        ];
90        for (action_str, action) in actions {
91            let deserialized = serde_json::from_str(action_str).unwrap();
92            assert_eq!(action, deserialized);
93        }
94    }
95
96    #[test]
97    fn should_deserialize_title_changes() {
98        let json = json!({
99            "title": {
100                "from": "test"
101            }
102        });
103        let deserialized = serde_json::from_value::<PullRequestChanges>(json).unwrap();
104        assert_eq!(
105            deserialized,
106            PullRequestChanges {
107                title: Some(PullRequestEventChangesFrom {
108                    from: "test".to_owned()
109                }),
110                body: None,
111            },
112        );
113    }
114
115    #[test]
116    fn should_deserialize_body_changes() {
117        let json = json!({
118            "body": {
119                "from": "test"
120            }
121        });
122        let deserialized = serde_json::from_value::<PullRequestChanges>(json).unwrap();
123        assert_eq!(
124            deserialized,
125            PullRequestChanges {
126                title: None,
127                body: Some(PullRequestEventChangesFrom {
128                    from: "test".to_owned()
129                }),
130            },
131        );
132    }
133
134    #[test]
135    fn should_deserialize_empty_changes() {
136        let json = json!({});
137        let deserialized = serde_json::from_value::<PullRequestChanges>(json).unwrap();
138        assert_eq!(
139            deserialized,
140            PullRequestChanges {
141                title: None,
142                body: None,
143            },
144        );
145    }
146
147    #[test]
148    fn should_deserialize_with_correct_payload() {
149        let json = include_str!("../../../../tests/resources/pull_request_event.json");
150        let event: Event = serde_json::from_str(json).unwrap();
151        if let Some(EventPayload::PullRequestEvent(ref payload)) =
152            event.payload.as_ref().unwrap().specific
153        {
154            assert_eq!(payload.action, PullRequestEventAction::Opened);
155            assert_eq!(payload.number, 8);
156            assert_eq!(payload.pull_request.id.0, 558121796);
157        } else {
158            panic!("unexpected event payload encountered: {:#?}", event.payload);
159        }
160    }
161}