From 69c786933f4b67d2ff857d609dc31fca9e1828b9 Mon Sep 17 00:00:00 2001 From: Mike Stemle Date: Sat, 13 Jan 2024 05:29:24 -0500 Subject: [PATCH] Repairing two 204-related serde errors, and adding some simple tests. (#503) --- CHANGELOG.md | 12 +++ src/api/issues.rs | 5 +- src/api/teams/team_repos.rs | 8 +- tests/issues_labels_delete_test.rs | 103 +++++++++++++++++++++++ tests/resources/issues_remove_label.json | 11 +++ tests/team_delete_test.rs | 56 ++++++++++++ tests/team_repos_tests.rs | 89 ++++++++++++++++++++ 7 files changed, 281 insertions(+), 3 deletions(-) create mode 100644 tests/issues_labels_delete_test.rs create mode 100644 tests/resources/issues_remove_label.json create mode 100644 tests/team_delete_test.rs create mode 100644 tests/team_repos_tests.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 4941ff18..8befe56c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed + +- Fixed two functions which return 204s and have no body, which throws serde errors + - `octocrab.issues().delete_label()` + - `octocrab.teams().repos().remove()` + +### Other + +- Added tests for the above functions +- Also added tests for `octocrab.teams().repos().add_or_update()` +- Also added tests for `octocrab.issues().remove_label()` + ## [0.32.0](https://github.com/XAMPPRocky/octocrab/compare/v0.31.2...v0.31.3) - 2023-11-01 ### Other diff --git a/src/api/issues.rs b/src/api/issues.rs index f2c33475..fb0b592e 100644 --- a/src/api/issues.rs +++ b/src/api/issues.rs @@ -472,7 +472,7 @@ impl<'octo> IssueHandler<'octo> { /// # Ok(()) /// # } /// ``` - pub async fn delete_label(&self, name: impl AsRef) -> Result { + pub async fn delete_label(&self, name: impl AsRef) -> Result<()> { let route = format!( "/repos/{owner}/{repo}/labels/{name}", owner = self.owner, @@ -480,7 +480,8 @@ impl<'octo> IssueHandler<'octo> { name = name.as_ref(), ); - self.crab.delete(route, None::<&()>).await + self.crab._delete(route, None::<&()>).await?; + Ok(()) } /// List labels from an issue on a repository. diff --git a/src/api/teams/team_repos.rs b/src/api/teams/team_repos.rs index b43012fb..3e8f44b3 100644 --- a/src/api/teams/team_repos.rs +++ b/src/api/teams/team_repos.rs @@ -132,6 +132,12 @@ impl<'octo> TeamRepoHandler<'octo> { owner = repo_owner.into(), repo = repo_name.into(), ); - self.crab.delete(route, None::<&()>).await + self.crab + ._delete( + self.crab.parameterized_uri(route, None::<&()>)?, + None::<&()>, + ) + .await?; + Ok(()) } } diff --git a/tests/issues_labels_delete_test.rs b/tests/issues_labels_delete_test.rs new file mode 100644 index 00000000..6616f967 --- /dev/null +++ b/tests/issues_labels_delete_test.rs @@ -0,0 +1,103 @@ +mod mock_error; + +use mock_error::setup_error_handler; +use octocrab::{models, Octocrab}; +// use serde::{Deserialize, Serialize}; +use wiremock::{ + matchers::{method, path}, + Mock, MockServer, ResponseTemplate, +}; + +async fn setup_remove_label_api(template: ResponseTemplate) -> MockServer { + let owner: &str = "org"; + let repo: &str = "some-repo"; + let issue_number: u64 = 123; + // Gotta love URL encoding + let label_name: &str = "some%2Dlabel"; + + let mock_server = MockServer::start().await; + + Mock::given(method("DELETE")) + .and(path(format!( + "/repos/{owner}/{repo}/issues/{issue_number}/labels/{label_name}" + ))) + .respond_with(template.clone()) + .mount(&mock_server) + .await; + + setup_error_handler( + &mock_server, + &format!("DELETE on /repos/{owner}/{repo}/issues/{issue_number}/labels/{label_name} was not received"), + ) + .await; + mock_server +} + +async fn setup_delete_label_api(template: ResponseTemplate) -> MockServer { + let owner: &str = "org"; + let repo: &str = "some-repo"; + let label_name: &str = "some%2Dlabel"; + + let mock_server = MockServer::start().await; + + Mock::given(method("DELETE")) + .and(path(format!("/repos/{owner}/{repo}/labels/{label_name}"))) + .respond_with(template.clone()) + .mount(&mock_server) + .await; + + setup_error_handler( + &mock_server, + &format!("DELETE on /repos/{owner}/{repo}/labels/{label_name} was not received"), + ) + .await; + mock_server +} + +fn setup_octocrab(uri: &str) -> Octocrab { + Octocrab::builder().base_uri(uri).unwrap().build().unwrap() +} + +const OWNER: &str = "org"; +const REPO: &str = "some-repo"; +const ISSUE_NUMBER: u64 = 123; +const LABEL_NAME: &str = "some-label"; + +#[tokio::test] +async fn should_remove_label() { + let remaining_issue_labels: Vec = + serde_json::from_str(include_str!("resources/issues_remove_label.json")).unwrap(); + + let template = ResponseTemplate::new(200).set_body_json(&remaining_issue_labels); + let mock_server = setup_remove_label_api(template).await; + let client = setup_octocrab(&mock_server.uri()); + + let issues = client.issues(OWNER.to_owned(), REPO.to_owned()); + + let result = issues + .remove_label(ISSUE_NUMBER, LABEL_NAME.to_owned()) + .await; + + assert!( + result.is_ok(), + "expected successful result, got error: {:#?}", + result + ); +} + +#[tokio::test] +async fn should_delete_label() { + let template = ResponseTemplate::new(204); + let mock_server = setup_delete_label_api(template).await; + let client = setup_octocrab(&mock_server.uri()); + + let issues = client.issues(OWNER.to_owned(), REPO.to_owned()); + + let result = issues.delete_label(LABEL_NAME.to_owned()).await; + + assert!( + result.is_ok(), + "expected successful result, got error: {:#?}", + result + ); +} diff --git a/tests/resources/issues_remove_label.json b/tests/resources/issues_remove_label.json new file mode 100644 index 00000000..cc0ea1a0 --- /dev/null +++ b/tests/resources/issues_remove_label.json @@ -0,0 +1,11 @@ +[ + { + "id": 208045946, + "node_id": "MDU6TGFiZWwyMDgwNDU5NDY=", + "url": "https://api.github.com/repos/octocat/Hello-World/labels/bug", + "name": "bug", + "description": "Something isn't working", + "color": "f29513", + "default": true + } +] diff --git a/tests/team_delete_test.rs b/tests/team_delete_test.rs new file mode 100644 index 00000000..ad08cf1a --- /dev/null +++ b/tests/team_delete_test.rs @@ -0,0 +1,56 @@ +// Tests for calls to the /orgs/{org}/teams/{team}/members API. +mod mock_error; + +use mock_error::setup_error_handler; +use octocrab::Octocrab; +use serde::{Deserialize, Serialize}; +use wiremock::{ + matchers::{method, path}, + Mock, MockServer, ResponseTemplate, +}; + +#[derive(Serialize, Deserialize)] +struct FakePage { + items: Vec, +} + +async fn setup_api(template: ResponseTemplate) -> MockServer { + let org = "org"; + let team = "team-name"; + let mock_server = MockServer::start().await; + + Mock::given(method("DELETE")) + .and(path(format!("/orgs/{org}/teams/{team}"))) + .respond_with(template.clone()) + .mount(&mock_server) + .await; + + setup_error_handler( + &mock_server, + &format!("DELETE on /orgs/{org}/teams/{team} was not received"), + ) + .await; + mock_server +} + +fn setup_octocrab(uri: &str) -> Octocrab { + Octocrab::builder().base_uri(uri).unwrap().build().unwrap() +} + +const ORG: &str = "org"; +const TEAM: &str = "team-name"; + +#[tokio::test] +async fn should_delete_team() { + let template = ResponseTemplate::new(204); + let mock_server = setup_api(template).await; + let client = setup_octocrab(&mock_server.uri()); + let teams = client.teams(ORG.to_owned()); + + let result = teams.delete(TEAM.to_owned()).await; + assert!( + result.is_ok(), + "expected successful result, got error: {:#?}", + result + ); +} diff --git a/tests/team_repos_tests.rs b/tests/team_repos_tests.rs new file mode 100644 index 00000000..dacf4e7b --- /dev/null +++ b/tests/team_repos_tests.rs @@ -0,0 +1,89 @@ +// Tests for calls to the /orgs/{org}/teams/{team}/members API. +mod mock_error; + +use mock_error::setup_error_handler; +use octocrab::Octocrab; +use serde::{Deserialize, Serialize}; +use wiremock::{ + matchers::{method, path}, + Mock, MockServer, ResponseTemplate, +}; + +#[derive(Serialize, Deserialize)] +struct FakePage { + items: Vec, +} + +async fn setup_api(template: ResponseTemplate) -> MockServer { + let org = "org"; + let team = "team-name"; + let repo = "testing"; + let mock_server = MockServer::start().await; + + Mock::given(method("DELETE")) + .and(path(format!("/orgs/{org}/teams/{team}/repos/{org}/{repo}"))) + .respond_with(template.clone()) + .mount(&mock_server) + .await; + Mock::given(method("PUT")) + .and(path(format!("/orgs/{org}/teams/{team}/repos/{org}/{repo}"))) + .respond_with(template.clone()) + .mount(&mock_server) + .await; + + setup_error_handler( + &mock_server, + &format!("DELETE on /orgs/{org}/teams/{team}/repos/{org}/{repo} was not received"), + ) + .await; + mock_server +} + +fn setup_octocrab(uri: &str) -> Octocrab { + Octocrab::builder().base_uri(uri).unwrap().build().unwrap() +} + +const ORG: &str = "org"; +const TEAM: &str = "team-name"; +const REPO: &str = "testing"; + +#[tokio::test] +async fn should_remove_team_repo() { + let template = ResponseTemplate::new(204); + let mock_server = setup_api(template).await; + let client = setup_octocrab(&mock_server.uri()); + let teams = client.teams(ORG.to_owned()); + + let result = teams + .repos(TEAM.to_owned()) + .remove(ORG.to_owned(), REPO.to_owned()) + .await; + assert!( + result.is_ok(), + "expected successful result, got error: {:#?}", + result + ); +} + +#[tokio::test] +async fn should_add_or_update_team_repo() { + let template = ResponseTemplate::new(204); + let mock_server = setup_api(template).await; + let client = setup_octocrab(&mock_server.uri()); + let teams = client.teams(ORG.to_owned()); + + let result = teams + .repos(TEAM.to_owned()) + .add_or_update( + ORG.to_owned(), + REPO.to_owned(), + Some(octocrab::params::teams::Permission::Push), + ) + .await; + assert!( + result.is_ok(), + "expected successful result, got error: {:#?}", + result + ); + eprintln!("Result: {result:#?}"); +}