omni_dev/atlassian/
api.rs1use std::future::Future;
8use std::pin::Pin;
9
10use anyhow::Result;
11
12use crate::atlassian::adf_validated::ValidatedAdfDocument;
13
14#[derive(Debug, Clone)]
16pub struct ContentItem {
17 pub id: String,
19
20 pub title: String,
22
23 pub body_adf: Option<serde_json::Value>,
25
26 pub metadata: ContentMetadata,
28}
29
30#[derive(Debug, Clone)]
32pub enum ContentMetadata {
33 Jira {
35 status: Option<String>,
37 issue_type: Option<String>,
39 assignee: Option<String>,
41 priority: Option<String>,
43 labels: Vec<String>,
45 },
46 Confluence {
48 space_key: String,
50 status: Option<String>,
52 version: Option<u32>,
54 parent_id: Option<String>,
56 },
57}
58
59pub trait AtlassianApi: Send + Sync {
64 fn get_content<'a>(
66 &'a self,
67 id: &'a str,
68 ) -> Pin<Box<dyn Future<Output = Result<ContentItem>> + Send + 'a>>;
69
70 fn update_content<'a>(
75 &'a self,
76 id: &'a str,
77 body_adf: &'a ValidatedAdfDocument,
78 title: Option<&'a str>,
79 ) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>>;
80
81 fn verify_auth<'a>(&'a self) -> Pin<Box<dyn Future<Output = Result<String>> + Send + 'a>>;
83
84 fn backend_name(&self) -> &'static str;
86}
87
88#[cfg(test)]
89#[allow(
90 clippy::unwrap_used,
91 clippy::expect_used,
92 clippy::match_wildcard_for_single_variants
93)]
94mod tests {
95 use super::*;
96
97 #[test]
98 fn content_metadata_jira_variant() {
99 let meta = ContentMetadata::Jira {
100 status: Some("Open".to_string()),
101 issue_type: Some("Bug".to_string()),
102 assignee: None,
103 priority: Some("High".to_string()),
104 labels: vec!["backend".to_string()],
105 };
106 match &meta {
107 ContentMetadata::Jira { status, labels, .. } => {
108 assert_eq!(status.as_deref(), Some("Open"));
109 assert_eq!(labels.len(), 1);
110 }
111 _ => panic!("Expected Jira variant"),
112 }
113 }
114
115 #[test]
116 fn content_metadata_confluence_variant() {
117 let meta = ContentMetadata::Confluence {
118 space_key: "ENG".to_string(),
119 status: Some("current".to_string()),
120 version: Some(7),
121 parent_id: None,
122 };
123 match &meta {
124 ContentMetadata::Confluence {
125 space_key, version, ..
126 } => {
127 assert_eq!(space_key, "ENG");
128 assert_eq!(*version, Some(7));
129 }
130 _ => panic!("Expected Confluence variant"),
131 }
132 }
133
134 #[test]
135 fn content_item_fields() {
136 let item = ContentItem {
137 id: "PROJ-123".to_string(),
138 title: "Fix the bug".to_string(),
139 body_adf: None,
140 metadata: ContentMetadata::Jira {
141 status: None,
142 issue_type: None,
143 assignee: None,
144 priority: None,
145 labels: vec![],
146 },
147 };
148 assert_eq!(item.id, "PROJ-123");
149 assert_eq!(item.title, "Fix the bug");
150 assert!(item.body_adf.is_none());
151 }
152}