phabricator_api/maniphest/
info.rs

1use super::str_or_u32;
2use crate::types::Phid;
3use crate::ApiRequest;
4use chrono::DateTime;
5use chrono::TimeZone;
6use chrono::Utc;
7use serde::de::Deserializer;
8use serde::Deserialize;
9use serde::Serialize;
10use serde_json::value::Value as JsonValue;
11use std::collections::HashMap;
12
13fn deserialize_date<'de, D>(d: D) -> Result<DateTime<Utc>, D::Error>
14where
15    D: Deserializer<'de>,
16{
17    let s = String::deserialize(d)?;
18    let date: i64 = s.parse().map_err(serde::de::Error::custom)?;
19
20    Ok(Utc.timestamp(date, 0))
21}
22
23#[derive(Serialize, Debug)]
24pub struct Info {
25    pub task_id: u32,
26}
27
28#[derive(Deserialize, Debug)]
29pub struct InfoResult {
30    #[serde(rename = "objectName")]
31    name: String,
32    #[serde(rename = "authorPHID")]
33    author: Phid,
34    #[serde(rename = "ccPHIDs")]
35    cc: Vec<Phid>,
36    title: String,
37    description: String,
38    uri: String,
39    #[serde(deserialize_with = "str_or_u32")]
40    id: u32,
41    #[serde(rename = "isClosed")]
42    closed: bool,
43    phid: Phid,
44    #[serde(rename = "ownerPHID")]
45    owner: Option<Phid>,
46    priority: String,
47    #[serde(rename = "projectPHIDs")]
48    projects: Vec<Phid>,
49    auxiliary: HashMap<String, Option<JsonValue>>,
50    status: String,
51    #[serde(rename = "statusName")]
52    status_name: String,
53    #[serde(rename = "priorityColor")]
54    priority_color: String,
55    #[serde(rename = "dependsOnTaskPHIDs")]
56    depends_on: Vec<Phid>,
57    #[serde(rename = "dateCreated", deserialize_with = "deserialize_date")]
58    created: DateTime<Utc>,
59    #[serde(rename = "dateModified", deserialize_with = "deserialize_date")]
60    modified: DateTime<Utc>,
61    #[serde(flatten)]
62    unparsed: serde_json::value::Value,
63}
64
65impl ApiRequest for Info {
66    type Reply = InfoResult;
67    const ROUTE: &'static str = "api/maniphest.info";
68}
69
70#[cfg(test)]
71mod test {
72    use super::*;
73    use phabricator_mock::task::Task;
74    use phabricator_mock::PhabMockServer;
75
76    fn compare_task(server: &Task, response: &InfoResult) {
77        assert_eq!(server.id, response.id);
78        assert_eq!(server.full_name, response.title);
79        assert_eq!(server.description, response.description);
80        // TODO compare more fields
81    }
82
83    #[tokio::test]
84    async fn simple() {
85        let m = PhabMockServer::start().await;
86        let user = m.new_user("user", "Test User");
87        m.new_simple_task(100, &user);
88
89        let client = crate::Client::new(m.uri(), m.token().to_string());
90        let i = Info { task_id: 100 };
91
92        let r = client.request(&i).await.unwrap();
93
94        let server_task = m.get_task(100).unwrap();
95
96        compare_task(&server_task, &r);
97    }
98
99    #[tokio::test]
100    async fn no_result() {
101        let m = PhabMockServer::start().await;
102
103        let client = crate::Client::new(m.uri(), m.token().to_string());
104        let i = Info { task_id: 100 };
105
106        client.request(&i).await.unwrap_err();
107    }
108}