phabricator_api/edge/
search.rs

1use crate::types::{Cursor, Phid};
2use crate::ApiRequest;
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Deserialize, Serialize, PartialEq, Eq)]
6pub enum Type {
7    #[serde(rename = "task.subtask")]
8    TaskSubtask,
9    #[serde(rename = "task.parent")]
10    TaskParent,
11}
12
13#[derive(Serialize, Debug, Default)]
14pub struct Search {
15    #[serde(rename = "sourcePHIDs")]
16    pub sources: Vec<Phid>,
17    pub types: Vec<Type>,
18    #[serde(rename = "destinationPHIDs")]
19    pub destinations: Option<Vec<Phid>>,
20}
21
22#[derive(Serialize, Debug)]
23pub struct SearchCursor<'a> {
24    #[serde(flatten)]
25    pub cursor: &'a Cursor,
26    #[serde(flatten)]
27    pub search: &'a Search,
28}
29
30#[derive(Deserialize, Debug)]
31pub struct Data {
32    #[serde(rename = "sourcePHID")]
33    pub source: Phid,
34    #[serde(rename = "edgeType")]
35    pub ty: Type,
36    #[serde(rename = "destinationPHID")]
37    pub dest: Phid,
38}
39
40#[derive(Deserialize, Debug)]
41pub struct SearchResult {
42    pub data: Vec<Data>,
43    pub cursor: Cursor,
44}
45
46impl ApiRequest for Search {
47    type Reply = SearchResult;
48    const ROUTE: &'static str = "api/edge.search";
49}
50
51impl ApiRequest for SearchCursor<'_> {
52    type Reply = SearchResult;
53    const ROUTE: &'static str = "api/edge.search";
54}
55
56#[cfg(test)]
57mod test {
58    use super::*;
59    use crate::types::Phid;
60    use phabricator_mock::task;
61    use phabricator_mock::PhabMockServer;
62
63    #[tokio::test]
64    async fn simple() {
65        let m = PhabMockServer::start().await;
66        let user = m.new_user("user", "Test User");
67        let t100 = m.new_simple_task(100, &user);
68        let t200 = m.new_simple_task(200, &user);
69
70        task::link(&t100, &t200);
71
72        let client = crate::Client::new(m.uri(), m.token().to_string());
73        let s = Search {
74            sources: vec![Phid(t100.phid.to_string())],
75            types: vec![Type::TaskSubtask],
76            ..Default::default()
77        };
78
79        let r = client.request(&s).await.unwrap();
80        assert_eq!(r.data.len(), 1);
81        assert_eq!(t100.phid, r.data[0].source.0.as_str());
82        assert_eq!(t200.phid, r.data[0].dest.0.as_str());
83        assert_eq!(Type::TaskSubtask, r.data[0].ty);
84
85        let s = Search {
86            sources: vec![Phid(t200.phid.to_string())],
87            types: vec![Type::TaskParent],
88            ..Default::default()
89        };
90
91        let r = client.request(&s).await.unwrap();
92        assert_eq!(r.data.len(), 1);
93        assert_eq!(t200.phid, r.data[0].source.0.as_str());
94        assert_eq!(t100.phid, r.data[0].dest.0.as_str());
95        assert_eq!(Type::TaskParent, r.data[0].ty);
96    }
97}