stygian_graph/adapters/graphql_plugins/
jobber.rs1use std::collections::HashMap;
8
9use crate::ports::graphql_plugin::GraphQlTargetPlugin;
10use crate::ports::{GraphQlAuth, GraphQlAuthKind};
11
12pub struct JobberPlugin;
28
29impl GraphQlTargetPlugin for JobberPlugin {
30 fn name(&self) -> &'static str {
31 "jobber"
32 }
33
34 fn endpoint(&self) -> &'static str {
35 "https://api.getjobber.com/api/graphql"
36 }
37
38 fn version_headers(&self) -> HashMap<String, String> {
39 [(
40 "X-JOBBER-GRAPHQL-VERSION".to_string(),
41 "2025-04-16".to_string(),
42 )]
43 .into()
44 }
45
46 fn default_auth(&self) -> Option<GraphQlAuth> {
47 std::env::var("JOBBER_ACCESS_TOKEN")
48 .ok()
49 .map(|token| GraphQlAuth {
50 kind: GraphQlAuthKind::Bearer,
51 token,
52 header_name: None,
53 })
54 }
55
56 fn description(&self) -> &'static str {
57 "Jobber field-service management GraphQL API"
58 }
59}
60
61#[cfg(test)]
62#[allow(unsafe_code, clippy::expect_used)] mod tests {
64 use super::*;
65
66 #[test]
67 fn plugin_name_is_jobber() {
68 assert_eq!(JobberPlugin.name(), "jobber");
69 }
70
71 #[test]
72 fn endpoint_is_correct() {
73 assert_eq!(
74 JobberPlugin.endpoint(),
75 "https://api.getjobber.com/api/graphql"
76 );
77 }
78
79 #[test]
80 fn version_header_is_set() {
81 let headers = JobberPlugin.version_headers();
82 assert_eq!(
83 headers.get("X-JOBBER-GRAPHQL-VERSION").map(String::as_str),
84 Some("2025-04-16")
85 );
86 }
87
88 #[test]
89 fn default_auth_reads_env() {
90 let key = "JOBBER_ACCESS_TOKEN";
91 let prev = std::env::var(key).ok();
92 unsafe { std::env::set_var(key, "test-token-abc") };
94
95 let auth = JobberPlugin.default_auth();
96 assert!(auth.is_some(), "auth should be Some when env var is set");
97 let auth = auth.expect("auth should be Some when env var is set");
98 assert_eq!(auth.kind, GraphQlAuthKind::Bearer);
99 assert_eq!(auth.token, "test-token-abc");
100 assert!(auth.header_name.is_none());
101
102 match prev {
104 Some(v) => unsafe { std::env::set_var(key, v) },
105 None => unsafe { std::env::remove_var(key) },
106 }
107 }
108
109 #[test]
110 fn default_auth_absent_when_no_env() {
111 let key = "JOBBER_ACCESS_TOKEN";
112 let prev = std::env::var(key).ok();
113 unsafe { std::env::remove_var(key) };
115
116 assert!(JobberPlugin.default_auth().is_none());
117
118 if let Some(v) = prev {
120 unsafe { std::env::set_var(key, v) };
121 }
122 }
123
124 #[test]
125 fn description_is_non_empty() {
126 assert!(!JobberPlugin.description().is_empty());
127 }
128}