1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
use derive_builder::Builder;
use http::Method;
use std::borrow::Cow;
use crate::api::users::UserEssentials;
use crate::api::{Endpoint, ReturnsJsonResponse};
#[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct Attachment {
pub id: u64,
pub filename: String,
pub filesize: u64,
pub content_type: Option<String>,
#[serde(default)]
pub description: Option<String>,
pub content_url: String,
pub author: UserEssentials,
#[serde(
serialize_with = "crate::api::serialize_rfc3339",
deserialize_with = "crate::api::deserialize_rfc3339"
)]
pub created_on: time::OffsetDateTime,
}
#[derive(Debug, Builder)]
#[builder(setter(strip_option))]
pub struct GetAttachment {
id: u64,
}
impl<'a> ReturnsJsonResponse for GetAttachment {}
impl<'a> GetAttachment {
#[must_use]
pub fn builder() -> GetAttachmentBuilder {
GetAttachmentBuilder::default()
}
}
impl Endpoint for GetAttachment {
fn method(&self) -> Method {
Method::GET
}
fn endpoint(&self) -> Cow<'static, str> {
format!("attachments/{}.json", &self.id).into()
}
}
#[derive(Debug, Builder)]
#[builder(setter(strip_option))]
pub struct DeleteAttachment {
id: u64,
}
impl DeleteAttachment {
#[must_use]
pub fn builder() -> DeleteAttachmentBuilder {
DeleteAttachmentBuilder::default()
}
}
impl<'a> Endpoint for DeleteAttachment {
fn method(&self) -> Method {
Method::DELETE
}
fn endpoint(&self) -> Cow<'static, str> {
format!("attachments/{}.json", &self.id).into()
}
}
#[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct AttachmentWrapper<T> {
pub attachment: T,
}
#[cfg(test)]
mod test {
use super::*;
use pretty_assertions::assert_eq;
use std::error::Error;
use tracing_test::traced_test;
#[traced_test]
#[test]
fn test_get_attachment() -> Result<(), Box<dyn Error>> {
dotenv::dotenv()?;
let redmine = crate::api::Redmine::from_env()?;
let endpoint = GetAttachment::builder().id(3).build()?;
redmine.json_response_body::<_, AttachmentWrapper<Attachment>>(&endpoint)?;
Ok(())
}
#[traced_test]
#[test]
fn test_completeness_attachment_type() -> Result<(), Box<dyn Error>> {
dotenv::dotenv()?;
let redmine = crate::api::Redmine::from_env()?;
let endpoint = GetAttachment::builder().id(3).build()?;
let AttachmentWrapper { attachment: value } =
redmine.json_response_body::<_, AttachmentWrapper<serde_json::Value>>(&endpoint)?;
let o: Attachment = serde_json::from_value(value.clone())?;
let reserialized = serde_json::to_value(o)?;
assert_eq!(value, reserialized);
Ok(())
}
}