jira_core/model/
watcher.rs1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct Watcher {
6 pub self_url: String,
7 pub account_id: String,
8 pub display_name: String,
9 pub active: bool,
10}
11
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct Watchers {
14 pub issue_key: String,
15 pub is_watching: bool,
16 pub watch_count: u64,
17 pub watchers: Vec<Watcher>,
18}
19
20impl Watcher {
21 pub fn from_value(v: &Value) -> Option<Self> {
22 Some(Watcher {
23 self_url: v
24 .get("self")
25 .and_then(|s| s.as_str())
26 .unwrap_or("")
27 .to_string(),
28 account_id: v.get("accountId")?.as_str()?.to_string(),
29 display_name: v
30 .get("displayName")
31 .and_then(|n| n.as_str())
32 .unwrap_or("")
33 .to_string(),
34 active: v.get("active").and_then(|a| a.as_bool()).unwrap_or(true),
35 })
36 }
37}
38
39impl Watchers {
40 pub fn from_value(v: &Value, issue_key: &str) -> Option<Self> {
41 Some(Watchers {
42 issue_key: issue_key.to_string(),
43 is_watching: v
44 .get("isWatching")
45 .and_then(|b| b.as_bool())
46 .unwrap_or(false),
47 watch_count: v.get("watchCount").and_then(|c| c.as_u64()).unwrap_or(0),
48 watchers: v
49 .get("watchers")
50 .and_then(|w| w.as_array())
51 .map(|arr| arr.iter().filter_map(Watcher::from_value).collect())
52 .unwrap_or_default(),
53 })
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60 use serde_json::json;
61
62 #[test]
63 fn parses_watcher() {
64 let v = json!({
65 "self": "https://x.atlassian.net/rest/api/3/user?accountId=abc",
66 "accountId": "abc",
67 "displayName": "Alice",
68 "active": true
69 });
70 let w = Watcher::from_value(&v).unwrap();
71 assert_eq!(w.account_id, "abc");
72 assert_eq!(w.display_name, "Alice");
73 assert!(w.active);
74 }
75
76 #[test]
77 fn parses_watchers_envelope() {
78 let v = json!({
79 "isWatching": true,
80 "watchCount": 2,
81 "watchers": [
82 {"self": "", "accountId": "a", "displayName": "Alice", "active": true},
83 {"self": "", "accountId": "b", "displayName": "Bob", "active": false}
84 ]
85 });
86 let ws = Watchers::from_value(&v, "ABC-1").unwrap();
87 assert_eq!(ws.issue_key, "ABC-1");
88 assert!(ws.is_watching);
89 assert_eq!(ws.watch_count, 2);
90 assert_eq!(ws.watchers.len(), 2);
91 assert_eq!(ws.watchers[1].account_id, "b");
92 assert!(!ws.watchers[1].active);
93 }
94
95 #[test]
96 fn parses_empty_watchers() {
97 let v = json!({"isWatching": false, "watchCount": 0, "watchers": []});
98 let ws = Watchers::from_value(&v, "ABC-2").unwrap();
99 assert_eq!(ws.watch_count, 0);
100 assert!(ws.watchers.is_empty());
101 }
102}