Skip to main content

busbar_sf_tooling/client/
code_intelligence.rs

1use tracing::instrument;
2
3use crate::error::Result;
4
5impl super::ToolingClient {
6    /// Get code completions for Apex system symbols.
7    ///
8    /// Returns the raw JSON response because the Salesforce completions
9    /// response format varies between Apex and Visualforce types and
10    /// across API versions.
11    ///
12    /// Available since API v28.0.
13    #[instrument(skip(self))]
14    pub async fn completions_apex(&self) -> Result<serde_json::Value> {
15        let url = self.client.tooling_url("completions?type=apex");
16        self.client.get_json(&url).await.map_err(Into::into)
17    }
18
19    /// Get code completions for Visualforce components.
20    ///
21    /// Returns the raw JSON response because the Salesforce completions
22    /// response format varies between Apex and Visualforce types and
23    /// across API versions.
24    ///
25    /// Available since API v38.0.
26    #[instrument(skip(self))]
27    pub async fn completions_visualforce(&self) -> Result<serde_json::Value> {
28        let url = self.client.tooling_url("completions?type=visualforce");
29        self.client.get_json(&url).await.map_err(Into::into)
30    }
31}
32
33#[cfg(test)]
34mod tests {
35    use super::super::ToolingClient;
36    use wiremock::matchers::{header, method, path, query_param};
37    use wiremock::{Mock, MockServer, ResponseTemplate};
38
39    #[tokio::test]
40    async fn test_completions_apex_wiremock() {
41        let mock_server = MockServer::start().await;
42
43        let mock_response = serde_json::json!({
44            "publicDeclarations": {
45                "System": [
46                    {
47                        "name": "debug",
48                        "type": "Method",
49                        "namespace": "System",
50                        "signature": "void debug(Object)"
51                    }
52                ]
53            }
54        });
55
56        Mock::given(method("GET"))
57            .and(path("/services/data/v62.0/tooling/completions"))
58            .and(query_param("type", "apex"))
59            .and(header("Authorization", "Bearer test-token"))
60            .respond_with(ResponseTemplate::new(200).set_body_json(mock_response))
61            .mount(&mock_server)
62            .await;
63
64        let client = ToolingClient::new(mock_server.uri(), "test-token").unwrap();
65        let completions = client
66            .completions_apex()
67            .await
68            .expect("completions_apex should succeed");
69        let pd = completions["publicDeclarations"]
70            .as_object()
71            .expect("should have publicDeclarations object");
72        assert!(pd.contains_key("System"));
73    }
74
75    #[tokio::test]
76    async fn test_completions_visualforce_wiremock() {
77        let mock_server = MockServer::start().await;
78
79        let mock_response = serde_json::json!({
80            "publicDeclarations": {
81                "apex": [
82                    {
83                        "name": "apex:page",
84                        "type": "Component",
85                        "namespace": "apex"
86                    }
87                ]
88            }
89        });
90
91        Mock::given(method("GET"))
92            .and(path("/services/data/v62.0/tooling/completions"))
93            .and(query_param("type", "visualforce"))
94            .and(header("Authorization", "Bearer test-token"))
95            .respond_with(ResponseTemplate::new(200).set_body_json(mock_response))
96            .mount(&mock_server)
97            .await;
98
99        let client = ToolingClient::new(mock_server.uri(), "test-token").unwrap();
100        let completions = client
101            .completions_visualforce()
102            .await
103            .expect("completions_visualforce should succeed");
104        let pd = completions["publicDeclarations"]
105            .as_object()
106            .expect("should have publicDeclarations object");
107        assert!(pd.contains_key("apex"));
108    }
109}