diff --git a/src/api/hooks.rs b/src/api/hooks.rs index 5ae6ba84..d849d765 100644 --- a/src/api/hooks.rs +++ b/src/api/hooks.rs @@ -1,14 +1,11 @@ //! The hooks API. -use crate::{Octocrab}; use crate::models::{HookDeliveryId, HookId}; +use crate::Octocrab; mod list_deliveries; mod retry_delivery; -pub use self::{ - list_deliveries::ListHooksDeliveriesBuilder, - retry_delivery::RetryDeliveryBuilder, -}; +pub use self::{list_deliveries::ListHooksDeliveriesBuilder, retry_delivery::RetryDeliveryBuilder}; /// A client to GitHub's webhooks API. /// @@ -63,7 +60,11 @@ impl<'octo> HooksHandler<'octo> { /// # Ok(()) /// # } /// ``` - pub fn retry_delivery(&self, hook_id: HookId, delivery_id: HookDeliveryId) -> RetryDeliveryBuilder<'_, '_> { + pub fn retry_delivery( + &self, + hook_id: HookId, + delivery_id: HookDeliveryId, + ) -> RetryDeliveryBuilder<'_, '_> { RetryDeliveryBuilder::new(self, hook_id, delivery_id) } } diff --git a/src/api/hooks/retry_delivery.rs b/src/api/hooks/retry_delivery.rs index 1d8b53de..ae28436d 100644 --- a/src/api/hooks/retry_delivery.rs +++ b/src/api/hooks/retry_delivery.rs @@ -1,7 +1,7 @@ +use super::*; +use crate::error::HttpSnafu; use http::Uri; use snafu::ResultExt; -use crate::error::HttpSnafu; -use super::*; /// A builder pattern struct for listing hooks deliveries. /// @@ -18,19 +18,29 @@ pub struct RetryDeliveryBuilder<'octo, 'r> { delivery_id: HookDeliveryId, } impl<'octo, 'r> RetryDeliveryBuilder<'octo, 'r> { - pub(crate) fn new(handler: &'r HooksHandler<'octo>, hook_id: HookId, delivery_id: HookDeliveryId) -> Self { + pub(crate) fn new( + handler: &'r HooksHandler<'octo>, + hook_id: HookId, + delivery_id: HookDeliveryId, + ) -> Self { Self { handler, hook_id, - delivery_id + delivery_id, } } /// Send the actual request. pub async fn send(self) -> crate::Result<()> { - let route= match self.handler.repo.clone() { - Some(repo) => format!("/repos/{}/{}/hooks/{}/deliveries/{}/attempts", self.handler.owner, repo, self.hook_id, self.delivery_id), - None => format!("/orgs/{}/hooks/{}/deliveries/{}/attempts", self.handler.owner, self.hook_id, self.delivery_id), + let route = match self.handler.repo.clone() { + Some(repo) => format!( + "/repos/{}/{}/hooks/{}/deliveries/{}/attempts", + self.handler.owner, repo, self.hook_id, self.delivery_id + ), + None => format!( + "/orgs/{}/hooks/{}/deliveries/{}/attempts", + self.handler.owner, self.hook_id, self.delivery_id + ), }; let uri = Uri::builder() @@ -40,34 +50,33 @@ impl<'octo, 'r> RetryDeliveryBuilder<'octo, 'r> { crate::map_github_error(self.handler.crab._post(uri, None::<&()>).await?) .await .map(drop) - } } #[cfg(test)] mod tests { - // use crate::models::HookId; + use crate::models::HookId; + + #[tokio::test] + async fn serialize() { + let octocrab = crate::Octocrab::default(); + let handler = octocrab.hooks("rust-lang"); + let list = handler + .list_deliveries(HookId::from(21u64)) + .per_page(100) + .page(1u8); - // #[tokio::test] - // async fn serialize() { - // let octocrab = crate::Octocrab::default(); - // let handler = octocrab.hooks("rust-lang"); - // let list = handler - // .list_deliveries(HookId::from(21u64)) - // .per_page(100) - // .page(1u8); - // - // assert_eq!( - // serde_json::to_value(list).unwrap(), - // serde_json::json!({ - // "state": "open", - // "head": "master", - // "base": "branch", - // "sort": "popularity", - // "direction": "asc", - // "per_page": 100, - // "page": 1, - // }) - // ) - // } + assert_eq!( + serde_json::to_value(list).unwrap(), + serde_json::json!({ + "state": "open", + "head": "master", + "base": "branch", + "sort": "popularity", + "direction": "asc", + "per_page": 100, + "page": 1, + }) + ) + } } diff --git a/tests/hooks_delivery_list.rs b/tests/hooks_delivery_list.rs new file mode 100644 index 00000000..08243691 --- /dev/null +++ b/tests/hooks_delivery_list.rs @@ -0,0 +1,89 @@ +/// Tests API calls related to check runs of a specific commit. +mod mock_error; + +use mock_error::setup_error_handler; +use octocrab::models::hooks::Delivery; +use octocrab::models::HookId; +use octocrab::{Error, Octocrab}; +use serde::{Deserialize, Serialize}; +use serde_json::{json, Value}; +use wiremock::{ + matchers::{method, path}, + Mock, MockServer, ResponseTemplate, +}; + +#[derive(Serialize, Deserialize)] +struct FakePage { + items: Vec, +} + +const OWNER: &str = "XAMPPRocky"; + +async fn setup_get_api(template: ResponseTemplate, number: u64) -> MockServer { + let mock_server = MockServer::start().await; + + Mock::given(method("GET")) + .and(path(format!("/orgs/{OWNER}/hooks/{number}/deliveries"))) + .respond_with(template) + .mount(&mock_server) + .await; + setup_error_handler( + &mock_server, + &format!("GET on /orgs/{OWNER}/hooks/{number}/deliveries was not received"), + ) + .await; + mock_server +} + +fn setup_octocrab(uri: &str) -> Octocrab { + Octocrab::builder().base_uri(uri).unwrap().build().unwrap() +} + +#[tokio::test] +async fn should_return_deliveries_for_org_by_id() { + let number: u64 = 148681297; + let mocked_response: Vec = + serde_json::from_str(include_str!("resources/hooks_delivery_list.json")).unwrap(); + let template = ResponseTemplate::new(200).set_body_json(&mocked_response); + let mock_server = setup_get_api(template, number).await; + let client = setup_octocrab(&mock_server.uri()); + let result = client + .hooks(OWNER) + .list_deliveries(HookId(number)) + .send() + .await; + + assert!( + result.is_ok(), + "expected successful result, got error: {:#?}", + result + ); + + let hooks = result.unwrap().items; + assert_eq!(hooks.len(), 2); +} + +#[tokio::test] +async fn should_fail_when_no_deliveries_found() { + let mocked_response = json!({ + "documentation_url": json!("rtm"), + "errors": Value::Null, + "message": json!("Its gone") + }); + + let template = ResponseTemplate::new(404).set_body_json(&mocked_response); + let mock_server = setup_get_api(template, 404).await; + let client = setup_octocrab(&mock_server.uri()); + let result = client + .hooks(OWNER) + .list_deliveries(HookId(404)) + .send() + .await; + + match result.unwrap_err() { + Error::GitHub { source, .. } => { + assert_eq!("Its gone", source.message) + } + other => panic!("Unexpected error: {:?}", other), + } +} diff --git a/tests/resources/hooks_delivery_list.json b/tests/resources/hooks_delivery_list.json new file mode 100644 index 00000000..1bde6b20 --- /dev/null +++ b/tests/resources/hooks_delivery_list.json @@ -0,0 +1,32 @@ +[ + { + "id": 93676014012, + "guid": "180a8f00-4a7c-11ef-8350-d1961bccd09f", + "delivered_at": "2024-07-25T11:50:32Z", + "redelivery": false, + "duration": 0.32, + "status": "Invalid HTTP Response: 503", + "status_code": 503, + "event": "workflow_job", + "action": "completed", + "installation_id": null, + "repository_id": 1, + "url": "", + "throttled_at": null + }, + { + "id": 93676002432, + "guid": "14d5f0e0-4a7c-11ef-8465-fadda1832ea4", + "delivered_at": "2024-07-25T11:50:26Z", + "redelivery": false, + "duration": 0.4, + "status": "OK", + "status_code": 200, + "event": "workflow_job", + "action": "in_progress", + "installation_id": null, + "repository_id": 1, + "url": "", + "throttled_at": null + } +]