Skip to main content

gitlab/api/projects/merge_requests/notes/
create.rs

1// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
2// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
3// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
4// option. This file may not be copied, modified, or distributed
5// except according to those terms.
6
7use chrono::{DateTime, Utc};
8use derive_builder::Builder;
9
10use crate::api::common::NameOrId;
11use crate::api::endpoint_prelude::*;
12
13/// Create a new note on a merge request on a project.
14#[derive(Debug, Builder, Clone)]
15#[builder(setter(strip_option))]
16pub struct CreateMergeRequestNote<'a> {
17    /// The project the merge request belongs to.
18    #[builder(setter(into))]
19    project: NameOrId<'a>,
20    /// The merge request to add the note to.
21    merge_request: u64,
22    /// The content of the note.
23    #[builder(setter(into))]
24    body: Cow<'a, str>,
25
26    /// Whether to create an internal note or not.
27    #[builder(default)]
28    internal: Option<bool>,
29    /// The creation date of the note.
30    ///
31    /// Requires administrator or owner permissions.
32    #[builder(default)]
33    created_at: Option<DateTime<Utc>>,
34    /// The SHA of the head of the merge request.
35    ///
36    /// Required when using the `/merge` command to verify that the intended commit is being
37    /// merged.
38    #[builder(setter(into), default)]
39    merge_request_diff_head_sha: Option<Cow<'a, str>>,
40}
41
42impl<'a> CreateMergeRequestNote<'a> {
43    /// Create a builder for the endpoint.
44    pub fn builder() -> CreateMergeRequestNoteBuilder<'a> {
45        CreateMergeRequestNoteBuilder::default()
46    }
47}
48
49impl Endpoint for CreateMergeRequestNote<'_> {
50    fn method(&self) -> Method {
51        Method::POST
52    }
53
54    fn endpoint(&self) -> Cow<'static, str> {
55        format!(
56            "projects/{}/merge_requests/{}/notes",
57            self.project, self.merge_request,
58        )
59        .into()
60    }
61
62    fn body(&self) -> Result<Option<(&'static str, Vec<u8>)>, BodyError> {
63        let mut params = FormParams::default();
64
65        params
66            .push("body", self.body.as_ref())
67            .push_opt("internal", self.internal)
68            .push_opt("created_at", self.created_at)
69            .push_opt(
70                "merge_request_diff_head_sha",
71                self.merge_request_diff_head_sha.as_ref(),
72            );
73
74        params.into_body()
75    }
76}
77
78#[cfg(test)]
79mod tests {
80    use chrono::{TimeZone, Utc};
81    use http::Method;
82
83    use crate::api::projects::merge_requests::notes::{
84        CreateMergeRequestNote, CreateMergeRequestNoteBuilderError,
85    };
86    use crate::api::{self, Query};
87    use crate::test::client::{ExpectedUrl, SingleTestClient};
88
89    #[test]
90    fn project_merge_request_and_body_are_necessary() {
91        let err = CreateMergeRequestNote::builder().build().unwrap_err();
92        crate::test::assert_missing_field!(err, CreateMergeRequestNoteBuilderError, "project");
93    }
94
95    #[test]
96    fn project_is_necessary() {
97        let err = CreateMergeRequestNote::builder()
98            .merge_request(1)
99            .body("body")
100            .build()
101            .unwrap_err();
102        crate::test::assert_missing_field!(err, CreateMergeRequestNoteBuilderError, "project");
103    }
104
105    #[test]
106    fn merge_request_is_necessary() {
107        let err = CreateMergeRequestNote::builder()
108            .project(1)
109            .body("body")
110            .build()
111            .unwrap_err();
112        crate::test::assert_missing_field!(
113            err,
114            CreateMergeRequestNoteBuilderError,
115            "merge_request",
116        );
117    }
118
119    #[test]
120    fn body_is_necessary() {
121        let err = CreateMergeRequestNote::builder()
122            .project(1)
123            .merge_request(1)
124            .build()
125            .unwrap_err();
126        crate::test::assert_missing_field!(err, CreateMergeRequestNoteBuilderError, "body");
127    }
128
129    #[test]
130    fn project_merge_request_and_body_are_sufficient() {
131        CreateMergeRequestNote::builder()
132            .project(1)
133            .merge_request(1)
134            .body("body")
135            .build()
136            .unwrap();
137    }
138
139    #[test]
140    fn endpoint() {
141        let endpoint = ExpectedUrl::builder()
142            .method(Method::POST)
143            .endpoint("projects/simple%2Fproject/merge_requests/1/notes")
144            .content_type("application/x-www-form-urlencoded")
145            .body_str("body=body")
146            .build()
147            .unwrap();
148        let client = SingleTestClient::new_raw(endpoint, "");
149
150        let endpoint = CreateMergeRequestNote::builder()
151            .project("simple/project")
152            .merge_request(1)
153            .body("body")
154            .build()
155            .unwrap();
156        api::ignore(endpoint).query(&client).unwrap();
157    }
158
159    #[test]
160    fn endpoint_internal() {
161        let endpoint = ExpectedUrl::builder()
162            .method(Method::POST)
163            .endpoint("projects/simple%2Fproject/merge_requests/1/notes")
164            .content_type("application/x-www-form-urlencoded")
165            .body_str(concat!("body=body", "&internal=true"))
166            .build()
167            .unwrap();
168        let client = SingleTestClient::new_raw(endpoint, "");
169
170        let endpoint = CreateMergeRequestNote::builder()
171            .project("simple/project")
172            .merge_request(1)
173            .body("body")
174            .internal(true)
175            .build()
176            .unwrap();
177        api::ignore(endpoint).query(&client).unwrap();
178    }
179
180    #[test]
181    fn endpoint_created_at() {
182        let endpoint = ExpectedUrl::builder()
183            .method(Method::POST)
184            .endpoint("projects/simple%2Fproject/merge_requests/1/notes")
185            .content_type("application/x-www-form-urlencoded")
186            .body_str(concat!("body=body", "&created_at=2020-01-01T00%3A00%3A00Z"))
187            .build()
188            .unwrap();
189        let client = SingleTestClient::new_raw(endpoint, "");
190
191        let endpoint = CreateMergeRequestNote::builder()
192            .project("simple/project")
193            .merge_request(1)
194            .body("body")
195            .created_at(Utc.with_ymd_and_hms(2020, 1, 1, 0, 0, 0).unwrap())
196            .build()
197            .unwrap();
198        api::ignore(endpoint).query(&client).unwrap();
199    }
200
201    #[test]
202    fn endpoint_merge_request_diff_head_sha() {
203        let endpoint = ExpectedUrl::builder()
204            .method(Method::POST)
205            .endpoint("projects/simple%2Fproject/merge_requests/1/notes")
206            .content_type("application/x-www-form-urlencoded")
207            .body_str(concat!(
208                "body=body",
209                "&merge_request_diff_head_sha=deadbeefdeadbeefdeadbeefdeadbeefdeadbeef",
210            ))
211            .build()
212            .unwrap();
213        let client = SingleTestClient::new_raw(endpoint, "");
214
215        let endpoint = CreateMergeRequestNote::builder()
216            .project("simple/project")
217            .merge_request(1)
218            .body("body")
219            .merge_request_diff_head_sha("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef")
220            .build()
221            .unwrap();
222        api::ignore(endpoint).query(&client).unwrap();
223    }
224}