Skip to main content

busbar_sf_tooling/client/
test_execution.rs

1use tracing::instrument;
2
3use crate::error::Result;
4use crate::types::{
5    RunTestsAsyncRequest, RunTestsRequest, RunTestsResponse, RunTestsSyncRequest,
6    RunTestsSyncResult, TestDiscoveryResult,
7};
8
9impl super::ToolingClient {
10    /// Run tests asynchronously.
11    ///
12    /// Returns the AsyncApexJob ID as a plain string.
13    #[instrument(skip(self, request))]
14    pub async fn run_tests_async(&self, request: &RunTestsAsyncRequest) -> Result<String> {
15        let url = format!(
16            "{}/services/data/v{}/tooling/runTestsAsynchronous/",
17            self.client.instance_url(),
18            self.client.api_version()
19        );
20
21        // Salesforce returns the job ID as a plain quoted JSON string, not an object
22        let job_id: String = self.client.post_json(&url, request).await?;
23        Ok(job_id)
24    }
25
26    /// Run tests synchronously.
27    ///
28    /// Blocks until completion. Returns full results including successes and failures.
29    #[instrument(skip(self, request))]
30    pub async fn run_tests_sync(
31        &self,
32        request: &RunTestsSyncRequest,
33    ) -> Result<RunTestsSyncResult> {
34        let url = format!(
35            "{}/services/data/v{}/tooling/runTestsSynchronous/",
36            self.client.instance_url(),
37            self.client.api_version()
38        );
39
40        self.client
41            .post_json(&url, request)
42            .await
43            .map_err(Into::into)
44    }
45
46    /// Discover available tests (Apex and Flow tests).
47    ///
48    /// **Requires API v65.0 or later.**
49    #[instrument(skip(self))]
50    pub async fn discover_tests(&self, category: Option<&str>) -> Result<TestDiscoveryResult> {
51        let mut url = format!(
52            "{}/services/data/v{}/tooling/tests/",
53            self.client.instance_url(),
54            self.client.api_version()
55        );
56
57        if let Some(cat) = category {
58            url = format!("{}?category={}", url, cat);
59        }
60
61        self.client.get_json(&url).await.map_err(Into::into)
62    }
63
64    /// Run tests using the unified Test Runner API (v65.0+).
65    #[instrument(skip(self, request))]
66    pub async fn run_tests(&self, request: &RunTestsRequest) -> Result<String> {
67        let url = format!(
68            "{}/services/data/v{}/tooling/tests/",
69            self.client.instance_url(),
70            self.client.api_version()
71        );
72
73        let response: RunTestsResponse = self.client.post_json(&url, request).await?;
74        Ok(response.test_run_id)
75    }
76}
77
78#[cfg(test)]
79mod tests {
80    use super::super::ToolingClient;
81
82    #[test]
83    fn test_run_tests_async_url() {
84        let client = ToolingClient::new("https://na1.salesforce.com", "token")
85            .unwrap()
86            .with_api_version("65.0");
87
88        let expected =
89            "https://na1.salesforce.com/services/data/v65.0/tooling/runTestsAsynchronous/";
90        let actual = format!(
91            "{}/services/data/v{}/tooling/runTestsAsynchronous/",
92            client.instance_url(),
93            client.api_version()
94        );
95        assert_eq!(actual, expected);
96    }
97
98    #[test]
99    fn test_run_tests_sync_url() {
100        let client = ToolingClient::new("https://na1.salesforce.com", "token")
101            .unwrap()
102            .with_api_version("62.0");
103
104        let expected =
105            "https://na1.salesforce.com/services/data/v62.0/tooling/runTestsSynchronous/";
106        let actual = format!(
107            "{}/services/data/v{}/tooling/runTestsSynchronous/",
108            client.instance_url(),
109            client.api_version()
110        );
111        assert_eq!(actual, expected);
112    }
113
114    #[test]
115    fn test_discover_tests_url() {
116        let client = ToolingClient::new("https://na1.salesforce.com", "token")
117            .unwrap()
118            .with_api_version("65.0");
119
120        let url_no_cat = format!(
121            "{}/services/data/v{}/tooling/tests/",
122            client.instance_url(),
123            client.api_version()
124        );
125        assert_eq!(
126            url_no_cat,
127            "https://na1.salesforce.com/services/data/v65.0/tooling/tests/"
128        );
129    }
130
131    #[test]
132    fn test_run_tests_url() {
133        let client = ToolingClient::new("https://na1.salesforce.com", "token")
134            .unwrap()
135            .with_api_version("65.0");
136
137        let expected = "https://na1.salesforce.com/services/data/v65.0/tooling/tests/";
138        let actual = format!(
139            "{}/services/data/v{}/tooling/tests/",
140            client.instance_url(),
141            client.api_version()
142        );
143        assert_eq!(actual, expected);
144    }
145}