From 741025721a39e2a07497cc89cca38226aa043336 Mon Sep 17 00:00:00 2001 From: gabriele Date: Mon, 21 Aug 2023 21:26:45 +0200 Subject: [PATCH 1/5] Add projects Api --- src/api.rs | 1 + src/api/projects.rs | 250 +++++++++++++ src/api/projects/projects.rs | 410 +++++++++++++++++++++ src/lib.rs | 9 +- tests/projects_org_create_project_test.rs | 65 ++++ tests/projects_org_list_projects_test.rs | 71 ++++ tests/projects_project_delete_test.rs | 56 +++ tests/projects_project_get_test.rs | 60 +++ tests/projects_project_update_test.rs | 61 +++ tests/projects_repo_create_project_test.rs | 67 ++++ tests/projects_repo_list_projects_test.rs | 71 ++++ tests/projects_user_create_project_test.rs | 61 +++ tests/projects_user_list_projects_test.rs | 62 ++++ tests/resources/project.json | 36 ++ tests/resources/projects.json | 72 ++++ tests/resources/user_projects.json | 70 ++++ 16 files changed, 1421 insertions(+), 1 deletion(-) create mode 100644 src/api/projects.rs create mode 100644 src/api/projects/projects.rs create mode 100644 tests/projects_org_create_project_test.rs create mode 100644 tests/projects_org_list_projects_test.rs create mode 100644 tests/projects_project_delete_test.rs create mode 100644 tests/projects_project_get_test.rs create mode 100644 tests/projects_project_update_test.rs create mode 100644 tests/projects_repo_create_project_test.rs create mode 100644 tests/projects_repo_list_projects_test.rs create mode 100644 tests/projects_user_create_project_test.rs create mode 100644 tests/projects_user_list_projects_test.rs create mode 100644 tests/resources/project.json create mode 100644 tests/resources/projects.json create mode 100644 tests/resources/user_projects.json diff --git a/src/api.rs b/src/api.rs index bbdc3282..5675ccdc 100644 --- a/src/api.rs +++ b/src/api.rs @@ -11,6 +11,7 @@ pub mod issues; pub mod licenses; pub mod markdown; pub mod orgs; +pub mod projects; pub mod pulls; pub mod ratelimit; pub mod repos; diff --git a/src/api/projects.rs b/src/api/projects.rs new file mode 100644 index 00000000..ba45aa2a --- /dev/null +++ b/src/api/projects.rs @@ -0,0 +1,250 @@ +//! The Projects API. +//! +//! # Notes +//! Users need an account with sufficient privileges to interact with projects. + +mod projects; + +use self::projects::{ + CreateOrgProjectsBuilder, CreateRepositoryProjectsBuilder, CreateUserProjectBuilder, + DeleteProjectBuilder, GetProjectBuilder, ListOrgProjectsBuilder, ListRepositoryProjectsBuilder, + ListUserProjectsBuilder, NotNamed, UpdateProjectBuilder, +}; +use crate::Octocrab; +use serde::Serialize; + +/// A struct to access GitHub's projects API. +/// +/// Created with [`Octocrab::projects`]. +pub struct ProjectHandler<'octo> { + crab: &'octo Octocrab, +} + +impl<'octo> ProjectHandler<'octo> { + pub(crate) fn new(crab: &'octo Octocrab) -> Self { + Self { crab } + } + + /// Get a project by its id. + /// + /// # Arguments + /// + /// * `project_id` - id of the project to fetch + /// + /// ```no_run + /// # async fn run() -> octocrab::Result<()> { + /// let project_id: u32 = 1002604; + /// let project = octocrab::instance() + /// .projects() + /// .get_project(project_id) + /// .send() + /// .await?; + /// # Ok(()) + /// # } + /// ``` + pub fn get_project(&self, project_id: impl Into) -> GetProjectBuilder<'_, '_> { + GetProjectBuilder::new(self, project_id.into()) + } + + /// Updates a project given its project id. + /// + /// # Arguments + /// + /// * `project_id` - id of the project to update + /// + /// ```no_run + /// # async fn run() -> octocrab::Result<()> { + /// let body = serde_json::json!({ "name": "Week One Sprint", "state": "open" }) + /// let project_id: u32 = 1002604; + /// let project = octocrab::instance() + /// .projects() + /// .update_project(project_id) + /// .body(body) + /// .send() + /// .await?; + /// # Ok(()) + /// # } + /// ``` + pub fn update_project(&self, project_id: impl Into) -> UpdateProjectBuilder<'_, '_, B> + where + B: Serialize + ?Sized, + { + UpdateProjectBuilder::new(self, project_id.into()) + } + + /// Deletes a project board. + /// + /// # Arguments + /// + /// * `project_id` - id of the project to delete + /// + /// ```no_run + /// # async fn run() -> octocrab::Result<()> { + /// let project_id: u32 = 1002604; + /// let project = octocrab::instance() + /// .projects() + /// .delete_project(project_id) + /// .send() + /// .await?; + /// # Ok(()) + /// # } + /// ``` + pub fn delete_project(&self, project_id: impl Into) -> DeleteProjectBuilder { + DeleteProjectBuilder::new(self, project_id.into()) + } + + /// Creates a user project board given its name. + /// + /// # Arguments + /// + /// * `username` - account username + /// + /// ```no_run + /// # async fn run() -> octocrab::Result<()> { + /// let username = "octocat"; + /// let description = "Project Overview" + /// let project = octocrab::instance() + /// .projects() + /// .create_user_project(username) + /// .body(description) + /// .send() + /// .await?; + /// # Ok(()) + /// # } + /// ``` + pub fn create_user_project(&self, username: impl Into) -> CreateUserProjectBuilder { + CreateUserProjectBuilder::new(self, username.into()) + } + + /// List a user's projects the username of the user + /// + /// # Arguments + /// + /// * `username` - account unsername + /// + /// ```no_run + /// # async fn run() -> octocrab::Result<()> { + /// let username = "octocat" + /// let project = octocrab::instance() + /// .projects() + /// .list_user_projects(username) + /// .send() + /// .await?; + /// # Ok(()) + /// # } + /// ``` + pub fn list_user_projects(&self, username: impl Into) -> ListUserProjectsBuilder { + ListUserProjectsBuilder::new(self, username.into()) + } + + /// List the projects of an organization. + /// + /// # Notes + /// Only users with sufficient privileges can list an organization's projects. + /// + /// # Arguments + /// + /// * `org` - name of the organization + /// + /// ```no_run + /// # async fn run() -> octocrab::Result<()> + /// let org = "octocrab" + /// let projects = octocrab::instance() + /// .projects() + /// .list_organization_projects(org) + /// .state("all") + /// .send() + /// .await?; + /// # OK(()) + /// # } + /// ``` + pub fn list_organization_projects( + &self, + org: impl Into, + ) -> ListOrgProjectsBuilder<'_, '_> { + ListOrgProjectsBuilder::new(self, org.into()) + } + + /// Create an organization project board. + /// + /// # Arguments + /// + /// * `org` - organization name. + /// * `name` - name of the project. + /// + /// ```no_run + /// # async fn run() -> octocrab::Result<()> { + /// let org = "octocrab", + /// let name = "Organization Roadmap" + /// let project = octocrab::instance() + /// .projects() + /// .create_organization_project(org, name) + /// .send() + /// .await?; + /// # OK(()) + /// # } + /// ``` + pub fn create_organization_project( + &self, + org: impl Into, + name: impl Into, + ) -> CreateOrgProjectsBuilder<'_, '_> { + CreateOrgProjectsBuilder::new(self, org.into(), name.into()) + } + + /// Creates a repository project board. + /// + /// # Arguments + /// + /// * `owner` - repository owner. + /// * `repo` - repository name. + /// + /// ```no_run + /// # async fn run() -> octocrab::Result<()> { + /// let owner = "octocat" + /// let repo = "octocrab" + /// let tags = octocrab::instance() + /// .projects() + /// .create_repository_project("owner", "repo") + /// .project_name(name) + /// .body(description) + /// .send() + /// .await?; + /// # Ok(()) + /// # } + /// ``` + pub fn create_repository_project( + &self, + owner: impl Into, + repo: impl Into, + ) -> CreateRepositoryProjectsBuilder<'_, '_, NotNamed> { + CreateRepositoryProjectsBuilder::instantiate(self, owner.into(), repo.into()) + } + + /// Lists the projects in a repository. + /// + /// # Arguments + /// + /// * `owner` - repository owner. + /// * `repo` - repository name. + /// + /// ```no_run + /// # async fn run() -> octocrab::Result<()> { + /// let owner = "octocat" + /// let repo = "octocrab" + /// let tags = octocrab::instance() + /// .projects() + /// .list_repository_projects("owner", "repo") + /// .send() + /// .await?; + /// # Ok(()) + /// # } + /// ``` + pub fn list_repository_projects( + &self, + owner: impl Into, + repo: impl Into, + ) -> ListRepositoryProjectsBuilder<'_, '_> { + ListRepositoryProjectsBuilder::new(self, owner.into(), repo.into()) + } +} diff --git a/src/api/projects/projects.rs b/src/api/projects/projects.rs new file mode 100644 index 00000000..5e8b4feb --- /dev/null +++ b/src/api/projects/projects.rs @@ -0,0 +1,410 @@ +//! A set of helper structs and implementations to manage projects + +use std::marker::PhantomData; + +use super::*; + +/// Helper builder struct to get a project by its id. +/// +/// Used by [`Octocrab::projects`]. +#[derive(serde::Serialize)] +pub struct GetProjectBuilder<'octo, 'r> { + #[serde(skip)] + handler: &'r ProjectHandler<'octo>, + project_id: u32, +} + +impl<'octo, 'r> GetProjectBuilder<'octo, 'r> { + pub fn new(handler: &'r ProjectHandler<'octo>, project_id: u32) -> Self { + Self { + handler, + project_id, + } + } + + pub async fn send(self) -> crate::Result { + let route = format!("/projects/{project_id}", project_id = self.project_id); + self.handler.crab.get(route, None::<&()>).await + } +} + +/// Helper builder struct to update a project by its id and body. +/// +/// Used by [`Octocrab::projects`]. +#[derive(serde::Serialize)] +pub struct UpdateProjectBuilder<'octo, 'r, B> +where + B: Serialize + ?Sized, +{ + #[serde(skip)] + handler: &'r ProjectHandler<'octo>, + project_id: u32, + #[serde(skip_serializing_if = "Option::is_none")] + body: Option<&'r B>, +} + +impl<'octo, 'r, B> UpdateProjectBuilder<'octo, 'r, B> +where + B: Serialize + ?Sized, +{ + pub fn new(handler: &'r ProjectHandler<'octo>, project_id: u32) -> Self { + Self { + handler, + project_id, + body: None, + } + } + + /// Set the body of the project. + /// + /// The input parameter `body` can specify the following keys: + /// - `name` (string) - name of the project + /// - `body` (string or null) - project description + /// - `state` (string) - `open` or `closed` + /// - `organization_permission` (string) - `read`, `write`, `admin`, `none`) + /// - `private` (boolean) + pub fn body(mut self, body: &'r B) -> Self { + self.body = Some(body); + self + } + + pub async fn send(self) -> crate::Result { + let route = format!("/projects/{project_id}", project_id = self.project_id); + + self.handler.crab.patch(route, Some(&self)).await + } +} + +/// Helper builder struct to delete a project by its id. +/// +/// Used by [`Octocrab::projects`]. +#[derive(serde::Serialize)] +pub struct DeleteProjectBuilder<'octo, 'r> { + #[serde(skip)] + handler: &'r ProjectHandler<'octo>, + project_id: u32, +} + +impl<'octo, 'r> DeleteProjectBuilder<'octo, 'r> { + pub fn new(handler: &'r ProjectHandler<'octo>, project_id: u32) -> Self { + Self { + handler, + project_id, + } + } + + pub async fn send(self) -> crate::Result { + let route = format!("/projects/{project_id}", project_id = self.project_id); + + self.handler.crab.delete(route, None::<&()>).await + } +} + +/// Helper builder struct to create a user project given its name. +/// +/// Used by [`Octocrab::projects`]. +#[derive(serde::Serialize)] +pub struct CreateUserProjectBuilder<'octo, 'r> { + #[serde(skip)] + handler: &'r ProjectHandler<'octo>, + #[serde(skip_serializing_if = "Option::is_none")] + body: Option, + name: String, +} +impl<'octo, 'r> CreateUserProjectBuilder<'octo, 'r> { + pub fn new(handler: &'r ProjectHandler<'octo>, name: String) -> Self { + Self { + handler, + name, + body: None, + } + } + + // The description of the project + pub fn body(mut self, body: impl Into) -> Self { + self.body = Some(body.into()); + self + } + + pub async fn send(self) -> crate::Result { + let route = "/user/projects"; + + self.handler.crab.post(route, Some(&self.body)).await + } +} + +/// Helper builder struct to list a user project given the username of the user. +/// +/// Used by [`Octocrab::projects`]. +#[derive(serde::Serialize)] +pub struct ListUserProjectsBuilder<'octo, 'r> { + #[serde(skip)] + handler: &'r ProjectHandler<'octo>, + #[serde(skip_serializing_if = "Option::is_none")] + per_page: Option, + #[serde(skip_serializing_if = "Option::is_none")] + page: Option, + username: String, +} +impl<'octo, 'r> ListUserProjectsBuilder<'octo, 'r> { + pub fn new(handler: &'r ProjectHandler<'octo>, username: String) -> Self { + Self { + handler: handler, + username: username, + per_page: None, + page: None, + } + } + + /// Results per page (max 100). + pub fn per_page(mut self, per_page: impl Into) -> Self { + self.per_page = Some(per_page.into()); + self + } + + /// Page number of the results to fetch. + pub fn page(mut self, page: impl Into) -> Self { + self.page = Some(page.into()); + self + } + + pub async fn send(self) -> crate::Result> { + let route = format!("/users/{username}/projects", username = self.username); + + self.handler.crab.get(route, None::<&()>).await + } +} + +/// Helper builder struct to get a paged list of an organization's projects. +/// +/// Used by [`Octocrab::orgs`]. +#[derive(serde::Serialize)] +pub struct ListOrgProjectsBuilder<'octo, 'r> { + #[serde(skip)] + handler: &'r ProjectHandler<'octo>, + #[serde(skip_serializing_if = "Option::is_none")] + per_page: Option, + #[serde(skip_serializing_if = "Option::is_none")] + page: Option, + #[serde(skip_serializing_if = "Option::is_none")] + state: Option, + org: String, +} + +impl<'octo, 'r> ListOrgProjectsBuilder<'octo, 'r> { + pub fn new(handler: &'r ProjectHandler<'octo>, org: String) -> Self { + Self { + handler, + per_page: None, + page: None, + state: None, + org: org, + } + } + + // Indicates the state of the projects to return. + // + // * `state` - state of the project. Default is `open` + // can be one of `open`, `closed`, `all` + pub fn state(mut self, state: impl Into) -> Self { + self.state = Some(state.into()); + self + } + + /// Results per page (max 100). + pub fn per_page(mut self, per_page: impl Into) -> Self { + self.per_page = Some(per_page.into()); + self + } + + /// Page number of the results to fetch. + pub fn page(mut self, page: impl Into) -> Self { + self.page = Some(page.into()); + self + } + + pub async fn send(self) -> crate::Result> { + let route = format!("/orgs/{org}/projects", org = self.org); + self.handler.crab.get(route, Some(&self)).await + } +} + +/// Helper builder struct to create an organization project. +/// +/// Used by [`Octocrab::orgs`]. +#[derive(serde::Serialize)] +pub struct CreateOrgProjectsBuilder<'octo, 'r> { + #[serde(skip)] + handler: &'r ProjectHandler<'octo>, + #[serde(skip_serializing_if = "Option::is_none")] + body: Option, + name: String, + org: String, +} + +impl<'octo, 'r> CreateOrgProjectsBuilder<'octo, 'r> { + pub fn new(handler: &'r ProjectHandler<'octo>, org: String, name: String) -> Self { + Self { + handler, + body: None, + name: name, + org: org, + } + } + + /// Description of the project. + pub fn body(mut self, description: impl Into) -> Self { + self.body = Some(description.into()); + self + } + + pub async fn send(self) -> crate::Result { + let route = format!("/orgs/{org}/projects", org = self.org); + self.handler.crab.post(route, Some(&self)).await + } +} + +/// Helper builder struct to get a paged list of repository projects +/// +/// Used by [`Octocrab::repos`]. +#[derive(serde::Serialize)] +pub struct ListRepositoryProjectsBuilder<'octo, 'r> { + #[serde(skip)] + handler: &'r ProjectHandler<'octo>, + #[serde(skip_serializing_if = "Option::is_none")] + per_page: Option, + #[serde(skip_serializing_if = "Option::is_none")] + page: Option, + owner: String, + repo: String, +} + +impl<'octo, 'r> ListRepositoryProjectsBuilder<'octo, 'r> { + pub fn new(handler: &'r ProjectHandler<'octo>, owner: String, repo: String) -> Self { + Self { + handler, + per_page: None, + page: None, + owner: owner, + repo: repo, + } + } + + /// Results per page (max 100). + pub fn per_page(mut self, per_page: impl Into) -> Self { + self.per_page = Some(per_page.into()); + self + } + + /// Page number of the results to fetch. + pub fn page(mut self, page: impl Into) -> Self { + self.page = Some(page.into()); + self + } + + /// Sends the actual request. + pub async fn send(self) -> crate::Result> { + let route = format!( + "/repos/{owner}/{repo}/projects", + owner = self.owner, + repo = self.repo + ); + self.handler.crab.get(route, Some(&self)).await + } +} + +pub struct Named; +pub struct NotNamed; + +/// Helper builder struct to get create a repository project +/// +/// Used by [`Octocrab::repos`]. +#[derive(serde::Serialize)] +pub struct CreateRepositoryProjectsBuilder<'octo, 'r, S> { + #[serde(skip)] + handler: &'r ProjectHandler<'octo>, + #[serde(skip_serializing_if = "Option::is_none")] + per_page: Option, + #[serde(skip_serializing_if = "Option::is_none")] + page: Option, + #[serde(skip_serializing_if = "Option::is_none")] + body: Option, + owner: String, + repo: String, + project_name: Option, + _named: std::marker::PhantomData, +} + +impl<'octo, 'r> CreateRepositoryProjectsBuilder<'octo, 'r, NotNamed> { + pub fn instantiate(handler: &'r ProjectHandler<'octo>, owner: String, repo: String) -> Self { + Self { + handler, + per_page: None, + page: None, + body: None, + owner: owner, + repo: repo, + project_name: None, + _named: PhantomData::default(), + } + } + + pub fn project_name( + self, + name: impl Into, + ) -> CreateRepositoryProjectsBuilder<'octo, 'r, Named> { + CreateRepositoryProjectsBuilder { + handler: self.handler, + per_page: self.per_page, + page: self.page, + body: self.body, + owner: self.owner, + repo: self.repo, + project_name: Some(name.into()), + _named: PhantomData::default(), + } + } +} + +impl<'octo, 'r> CreateRepositoryProjectsBuilder<'octo, 'r, Named> { + pub fn new(repo_builder: CreateRepositoryProjectsBuilder<'octo, 'r, NotNamed>) -> Self { + Self { + handler: repo_builder.handler, + per_page: None, + page: None, + body: None, + owner: repo_builder.owner, + repo: repo_builder.repo, + project_name: repo_builder.project_name, + _named: PhantomData::default(), + } + } + + /// Description of the project. + pub fn body(mut self, description: impl Into) -> Self { + self.body = Some(description.into()); + self + } + + /// Results per page (max 100). + pub fn per_page(mut self, per_page: impl Into) -> Self { + self.per_page = Some(per_page.into()); + self + } + + /// Page number of the results to fetch. + pub fn page(mut self, page: impl Into) -> Self { + self.page = Some(page.into()); + self + } + + /// Sends the actual request. + pub async fn send(self) -> crate::Result { + let route = format!( + "/repos/{owner}/{repo}/projects", + owner = self.owner, + repo = self.repo + ); + self.handler.crab.post(route, Some(&self)).await + } +} diff --git a/src/lib.rs b/src/lib.rs index 6e157e00..480f8437 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,6 +19,7 @@ //! - [`licenses`] License Metadata. //! - [`markdown`] Rendering Markdown with GitHub //! - [`orgs`] GitHub Organisations +//! - [`projects`] GitHub Projects //! - [`pulls`] Pull Requests //! - [`repos`] Repositories //! - [`repos::forks`] Repositories @@ -250,7 +251,7 @@ use models::{AppId, InstallationId, InstallationToken}; pub use self::{ api::{ actions, activity, apps, checks, commits, current, events, gists, gitignore, issues, - licenses, markdown, orgs, pulls, ratelimit, repos, search, teams, workflows, + licenses, markdown, orgs, projects, pulls, ratelimit, repos, search, teams, workflows, }, error::{Error, GitHubError}, from_response::FromResponse, @@ -1009,6 +1010,12 @@ impl Octocrab { repos::RepoHandler::new(self, owner.into(), repo.into()) } + /// Creates a [`projects::ProjectHandler`] that allows you to access GitHub's + /// projects API (classic). + pub fn projects(&self) -> projects::ProjectHandler { + projects::ProjectHandler::new(self) + } + /// Creates a [`search::SearchHandler`] that allows you to construct general queries /// to GitHub's API. pub fn search(&self) -> search::SearchHandler { diff --git a/tests/projects_org_create_project_test.rs b/tests/projects_org_create_project_test.rs new file mode 100644 index 00000000..292b940d --- /dev/null +++ b/tests/projects_org_create_project_test.rs @@ -0,0 +1,65 @@ +// Tests for calls to the /orgs/{org}/projects API. +mod mock_error; + +use mock_error::setup_error_handler; +use octocrab::{models::Project, Octocrab}; +use serde::{Deserialize, Serialize}; +use wiremock::{ + matchers::{method, path}, + Mock, MockServer, ResponseTemplate, +}; + +const ORG: &str = "octocat"; + +#[derive(Serialize, Deserialize)] +struct FakeProject(Project); + +async fn setup_api(template: ResponseTemplate) -> MockServer { + let mock_server = MockServer::start().await; + + Mock::given(method("POST")) + .and(path(format!("/orgs/{ORG}/projects"))) + .respond_with(template) + .mount(&mock_server) + .await; + setup_error_handler( + &mock_server, + &format!("POST on /orgs/{ORG}/projects 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_create_organization_project() { + let org_project: Project = + serde_json::from_str(include_str!("resources/project.json")).unwrap(); + + let test_name = org_project.name.clone(); + let test_description = org_project.body.clone(); + + let page_response = FakeProject(org_project); + + let template = ResponseTemplate::new(200).set_body_json(&page_response); + let mock_server = setup_api(template).await; + + let name = "Organization Roadmap"; + let description = "High-level roadmap for the upcoming year."; + + let client = setup_octocrab(&mock_server.uri()); + + let project = client + .projects() + .create_organization_project(ORG, name) + .body(description) + .send() + .await + .unwrap(); + + assert_eq!(project.name, test_name); + assert_eq!(project.body, test_description); +} diff --git a/tests/projects_org_list_projects_test.rs b/tests/projects_org_list_projects_test.rs new file mode 100644 index 00000000..29478c99 --- /dev/null +++ b/tests/projects_org_list_projects_test.rs @@ -0,0 +1,71 @@ +// Tests for calls to the /orgs/{org}/projects API. +mod mock_error; + +use mock_error::setup_error_handler; +use octocrab::{models::Project, Octocrab, Page}; +use serde::{Deserialize, Serialize}; +use wiremock::{ + matchers::{method, path}, + Mock, MockServer, ResponseTemplate, +}; + +const ORG: &str = "octocat"; + +#[derive(Serialize, Deserialize)] +struct FakePage { + items: Vec, +} + +async fn setup_api(template: ResponseTemplate) -> MockServer { + let mock_server = MockServer::start().await; + + Mock::given(method("GET")) + .and(path(format!("/orgs/{ORG}/projects"))) + .respond_with(template) + .mount(&mock_server) + .await; + setup_error_handler( + &mock_server, + &format!("GET on /orgs/{ORG}/projects 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_list_page_with_projects() { + let org_project: Vec = + serde_json::from_str(include_str!("resources/projects.json")).unwrap(); + let owner = org_project[0].creator.login.clone(); + + let page_response = FakePage { items: org_project }; + + let template = ResponseTemplate::new(200).set_body_json(&page_response); + let mock_server = setup_api(template).await; + + let client = setup_octocrab(&mock_server.uri()); + + let result = client + .projects() + .list_organization_projects(ORG) + .state("all") + .per_page(1) + .send() + .await; + + assert!( + result.is_ok(), + "expected successful result, got error: {:#?}", + result + ); + + let Page { items, .. } = result.unwrap(); + { + assert_eq!(items.len(), 2); + assert_eq!(items[0].creator.login, owner); + } +} diff --git a/tests/projects_project_delete_test.rs b/tests/projects_project_delete_test.rs new file mode 100644 index 00000000..aa3fbf3d --- /dev/null +++ b/tests/projects_project_delete_test.rs @@ -0,0 +1,56 @@ +// Tests for calls to the /projects/{project_id} API. +mod mock_error; + +use mock_error::setup_error_handler; +use octocrab::{models::Project, Octocrab}; +use serde::{Deserialize, Serialize}; +use wiremock::{ + matchers::{method, path}, + Mock, MockServer, ResponseTemplate, +}; + +const PROJECT_ID: u32 = 1002605; + +#[derive(Serialize, Deserialize)] +struct FakeProject(Project); + +async fn setup_api(template: ResponseTemplate) -> MockServer { + let mock_server = MockServer::start().await; + + Mock::given(method("DELETE")) + .and(path(format!("/projects/{PROJECT_ID}"))) + .respond_with(template) + .mount(&mock_server) + .await; + setup_error_handler( + &mock_server, + &format!("DELETE on /projects/{PROJECT_ID} 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_delete_project() { + let org_project: Project = + serde_json::from_str(include_str!("resources/project.json")).unwrap(); + + let page_response = FakeProject(org_project); + + let template = ResponseTemplate::new(200).set_body_json(&page_response); + let mock_server = setup_api(template).await; + + let client = setup_octocrab(&mock_server.uri()); + let project = client + .projects() + .delete_project(PROJECT_ID) + .send() + .await + .unwrap(); + + assert_eq!(project.creator.login, "octocat"); +} diff --git a/tests/projects_project_get_test.rs b/tests/projects_project_get_test.rs new file mode 100644 index 00000000..ff84075a --- /dev/null +++ b/tests/projects_project_get_test.rs @@ -0,0 +1,60 @@ +// Tests for calls to the /projects/{project_id} API. +mod mock_error; + +use mock_error::setup_error_handler; +use octocrab::{models::Project, Octocrab}; +use serde::{Deserialize, Serialize}; +use wiremock::{ + matchers::{method, path}, + Mock, MockServer, ResponseTemplate, +}; + +const PROJECT_ID: u32 = 1002605; + +#[derive(Serialize, Deserialize)] +struct FakeProject(Project); + +async fn setup_api(template: ResponseTemplate) -> MockServer { + let mock_server = MockServer::start().await; + + Mock::given(method("GET")) + .and(path(format!("/projects/{PROJECT_ID}"))) + .respond_with(template) + .mount(&mock_server) + .await; + setup_error_handler( + &mock_server, + &format!("GET on /projects/{PROJECT_ID} 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_get_projects_by_its_id() { + let org_project: Project = + serde_json::from_str(include_str!("resources/project.json")).unwrap(); + + let page_response = FakeProject(org_project); + + let template = ResponseTemplate::new(200).set_body_json(&page_response); + let mock_server = setup_api(template).await; + + let client = setup_octocrab(&mock_server.uri()); + let project = client.projects().get_project(PROJECT_ID).send().await; + + assert!( + project.is_ok(), + "expected successful result, got error: {:#?}", + project + ); + + let result = project.unwrap(); + + assert_eq!(result.name, "Organization Roadmap"); + assert_eq!(result.creator.login, "octocat"); +} diff --git a/tests/projects_project_update_test.rs b/tests/projects_project_update_test.rs new file mode 100644 index 00000000..0660deda --- /dev/null +++ b/tests/projects_project_update_test.rs @@ -0,0 +1,61 @@ +// Tests for calls to the /projects/{project_id} API. +mod mock_error; + +use mock_error::setup_error_handler; +use octocrab::{models::Project, Octocrab}; +use serde::{Deserialize, Serialize}; +use wiremock::{ + matchers::{method, path}, + Mock, MockServer, ResponseTemplate, +}; + +const PROJECT_ID: u32 = 1002605; + +#[derive(Serialize, Deserialize)] +struct FakeProject(Project); + +async fn setup_api(template: ResponseTemplate) -> MockServer { + let mock_server = MockServer::start().await; + + Mock::given(method("PATCH")) + .and(path(format!("/projects/{PROJECT_ID}"))) + .respond_with(template) + .mount(&mock_server) + .await; + setup_error_handler( + &mock_server, + &format!("PATCH on /projects/{PROJECT_ID} 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_update_project_name() { + let org_project: Project = + serde_json::from_str(include_str!("resources/project.json")).unwrap(); + + let test_name = org_project.name.clone(); + + let page_response = FakeProject(org_project); + + let template = ResponseTemplate::new(200).set_body_json(&page_response); + let mock_server = setup_api(template).await; + + let body = serde_json::json!({ "name": "Week One Sprint" }); + + let client = setup_octocrab(&mock_server.uri()); + let project = client + .projects() + .update_project(PROJECT_ID) + .body(&body) + .send() + .await + .unwrap(); + + assert_eq!(project.name, test_name); +} diff --git a/tests/projects_repo_create_project_test.rs b/tests/projects_repo_create_project_test.rs new file mode 100644 index 00000000..d5145451 --- /dev/null +++ b/tests/projects_repo_create_project_test.rs @@ -0,0 +1,67 @@ +// Tests for calls to the /repos/{owner}/{repo}/projects API. +mod mock_error; + +use mock_error::setup_error_handler; +use octocrab::{models::Project, Octocrab}; +use serde::{Deserialize, Serialize}; +use wiremock::{ + matchers::{method, path}, + Mock, MockServer, ResponseTemplate, +}; + +const OWNER: &str = "octocat"; +const REPO: &str = "repo"; + +#[derive(Serialize, Deserialize)] +struct FakeProject(Project); + +async fn setup_api(template: ResponseTemplate) -> MockServer { + let mock_server = MockServer::start().await; + + Mock::given(method("POST")) + .and(path(format!("/repos/{OWNER}/{REPO}/projects"))) + .respond_with(template) + .mount(&mock_server) + .await; + setup_error_handler( + &mock_server, + &format!("POST on /repos/{OWNER}/{REPO}/projects 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_create_org_project() { + let repo_project: Project = + serde_json::from_str(include_str!("resources/project.json")).unwrap(); + + let test_name = repo_project.creator.login.clone(); + let test_description = repo_project.body.clone(); + + let page_response = FakeProject(repo_project); + + let template = ResponseTemplate::new(200).set_body_json(&page_response); + let mock_server = setup_api(template).await; + + let client = setup_octocrab(&mock_server.uri()); + + let name = "Organization Roadmap"; + let description = "High-level roadmap for the upcoming year."; + + let result = client + .projects() + .create_repository_project(OWNER, REPO) + .project_name(name) + .body(description) + .send() + .await + .unwrap(); + + assert_eq!(result.creator.login, test_name); + assert_eq!(result.body, test_description); +} diff --git a/tests/projects_repo_list_projects_test.rs b/tests/projects_repo_list_projects_test.rs new file mode 100644 index 00000000..88c4c27b --- /dev/null +++ b/tests/projects_repo_list_projects_test.rs @@ -0,0 +1,71 @@ +// Tests for calls to the /repos/{owner}/{repo}/projects API. +mod mock_error; + +use mock_error::setup_error_handler; +use octocrab::{models::Project, Octocrab, Page}; +use serde::{Deserialize, Serialize}; +use wiremock::{ + matchers::{method, path}, + Mock, MockServer, ResponseTemplate, +}; + +const OWNER: &str = "octocat"; +const REPO: &str = "repo"; + +#[derive(Serialize, Deserialize)] +struct FakePage { + items: Vec, +} + +async fn setup_api(template: ResponseTemplate) -> MockServer { + let mock_server = MockServer::start().await; + + Mock::given(method("GET")) + .and(path(format!("/repos/{OWNER}/{REPO}/projects"))) + .respond_with(template) + .mount(&mock_server) + .await; + + setup_error_handler( + &mock_server, + &format!("GET on /repos/{OWNER}/{REPO}/projects 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_list_org_projects() { + let repo_project: Vec = + serde_json::from_str(include_str!("resources/projects.json")).unwrap(); + + let test_login = repo_project[0].creator.login.clone(); + let test_id = repo_project[1].id.clone(); + + let page_response = FakePage { + items: repo_project, + }; + + let template = ResponseTemplate::new(200).set_body_json(&page_response); + let mock_server = setup_api(template).await; + + let client = setup_octocrab(&mock_server.uri()); + let result = client + .projects() + .list_repository_projects(OWNER, REPO) + .per_page(100) + .send() + .await + .unwrap(); + + let Page { items, .. } = result; + { + assert_eq!(items.len(), 2); + assert_eq!(items[0].creator.login, test_login); + assert_eq!(items[1].id, test_id); + } +} diff --git a/tests/projects_user_create_project_test.rs b/tests/projects_user_create_project_test.rs new file mode 100644 index 00000000..94380d80 --- /dev/null +++ b/tests/projects_user_create_project_test.rs @@ -0,0 +1,61 @@ +// Tests for calls to the /projects/{project_id} API. +mod mock_error; + +use mock_error::setup_error_handler; +use octocrab::{models::Project, Octocrab}; +use serde::{Deserialize, Serialize}; +use wiremock::{ + matchers::{method, path}, + Mock, MockServer, ResponseTemplate, +}; + +const NAME: &str = "Organization Roadmap"; + +#[derive(Serialize, Deserialize)] +struct FakeProject(Project); + +async fn setup_api(template: ResponseTemplate) -> MockServer { + let mock_server = MockServer::start().await; + + Mock::given(method("POST")) + .and(path(format!("/user/projects"))) + .respond_with(template) + .mount(&mock_server) + .await; + setup_error_handler( + &mock_server, + &format!("POST on /users/projects 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_update_project_name() { + let org_project: Project = + serde_json::from_str(include_str!("resources/project.json")).unwrap(); + + let test_name = org_project.name.clone(); + + let page_response = FakeProject(org_project); + + let template = ResponseTemplate::new(200).set_body_json(&page_response); + let mock_server = setup_api(template).await; + + let description = "High-level roadmap for the upcoming year."; + + let client = setup_octocrab(&mock_server.uri()); + let result = client + .projects() + .create_user_project(NAME) + .body(description) + .send() + .await + .unwrap(); + + assert_eq!(result.name, test_name); +} diff --git a/tests/projects_user_list_projects_test.rs b/tests/projects_user_list_projects_test.rs new file mode 100644 index 00000000..09e7b816 --- /dev/null +++ b/tests/projects_user_list_projects_test.rs @@ -0,0 +1,62 @@ +// Tests for calls to the /users/{username}/projects API. +mod mock_error; + +use mock_error::setup_error_handler; +use octocrab::{models::Project, Octocrab, Page}; +use serde::{Deserialize, Serialize}; +use wiremock::{ + matchers::{method, path}, + Mock, MockServer, ResponseTemplate, +}; + +const USERNAME: &str = "octocat"; + +#[derive(Serialize, Deserialize)] +struct FakePage { + items: Vec, +} + +async fn setup_api(template: ResponseTemplate) -> MockServer { + let mock_server = MockServer::start().await; + + Mock::given(method("GET")) + .and(path(format!("/users/{USERNAME}/projects"))) + .respond_with(template) + .mount(&mock_server) + .await; + setup_error_handler( + &mock_server, + &format!("GET on /users/{USERNAME}/projects 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_get_projects_by_its_id() { + let org_project: Vec = + serde_json::from_str(include_str!("resources/user_projects.json")).unwrap(); + + let page_response = FakePage { items: org_project }; + + let template = ResponseTemplate::new(200).set_body_json(&page_response); + let mock_server = setup_api(template).await; + + let client = setup_octocrab(&mock_server.uri()); + let result = client.projects().list_user_projects(USERNAME).send().await; + + assert!( + result.is_ok(), + "expected successful result, got error: {:#?}", + result + ); + + let Page { items, .. } = result.unwrap(); + + assert_eq!(items[0].name, "My Projects"); + assert_eq!(items[1].creator.login, "octocat"); +} diff --git a/tests/resources/project.json b/tests/resources/project.json new file mode 100644 index 00000000..22c653ea --- /dev/null +++ b/tests/resources/project.json @@ -0,0 +1,36 @@ +{ + "owner_url": "https://api.github.com/orgs/octocat", + "url": "https://api.github.com/projects/1002605", + "html_url": "https://github.com/orgs/api-playground/projects/1", + "columns_url": "https://api.github.com/projects/1002605/columns", + "id": 1002605, + "node_id": "MDc6UHJvamVjdDEwMDI2MDU=", + "name": "Organization Roadmap", + "body": "High-level roadmap for the upcoming year.", + "number": 1, + "state": "open", + "creator": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false, + "patch_url": "", + "email": "" + }, + "created_at": "2011-04-11T20:09:31Z", + "updated_at": "2014-03-04T18:58:10Z" +} \ No newline at end of file diff --git a/tests/resources/projects.json b/tests/resources/projects.json new file mode 100644 index 00000000..af89ee50 --- /dev/null +++ b/tests/resources/projects.json @@ -0,0 +1,72 @@ +[ + { + "owner_url": "https://api.github.com/orgs/octocat", + "url": "https://api.github.com/projects/1002605", + "html_url": "https://github.com/orgs/api-playground/projects/1", + "columns_url": "https://api.github.com/projects/1002605/columns", + "id": 1002605, + "node_id": "MDc6UHJvamVjdDEwMDI2MDU=", + "name": "Organization Roadmap", + "body": "High-level roadmap for the upcoming year.", + "number": 1, + "state": "open", + "creator": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false, + "patch_url": "", + "email": "" + }, + "created_at": "2011-04-11T20:09:31Z", + "updated_at": "2014-03-04T18:58:10Z" + }, + { + "owner_url": "https://api.github.com/repos/api-playground/projects-test", + "url": "https://api.github.com/projects/1002604", + "html_url": "https://github.com/api-playground/projects-test/projects/1", + "columns_url": "https://api.github.com/projects/1002604/columns", + "id": 1002604, + "node_id": "MDc6UHJvamVjdDEwMDI2MDQ=", + "name": "Projects Documentation", + "body": "Developer documentation project for the developer site.", + "number": 1, + "state": "open", + "creator": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "created_at": "2011-04-10T20:09:31Z", + "updated_at": "2014-03-03T18:58:10Z" + } +] \ No newline at end of file diff --git a/tests/resources/user_projects.json b/tests/resources/user_projects.json new file mode 100644 index 00000000..5249d55b --- /dev/null +++ b/tests/resources/user_projects.json @@ -0,0 +1,70 @@ +[ + { + "owner_url": "https://api.github.com/users/octocat", + "url": "https://api.github.com/projects/1002603", + "html_url": "https://github.com/users/octocat/projects/1", + "columns_url": "https://api.github.com/projects/1002603/columns", + "id": 1002603, + "node_id": "MDc6UHJvamVjdDEwMDI2MDM=", + "name": "My Projects", + "body": "A board to manage my personal projects.", + "number": 1, + "state": "open", + "creator": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "created_at": "2011-04-10T20:09:31Z", + "updated_at": "2014-03-03T18:58:10Z" + }, + { + "owner_url": "https://api.github.com/repos/api-playground/projects-test", + "url": "https://api.github.com/projects/1002604", + "html_url": "https://github.com/api-playground/projects-test/projects/1", + "columns_url": "https://api.github.com/projects/1002604/columns", + "id": 1002604, + "node_id": "MDc6UHJvamVjdDEwMDI2MDQ=", + "name": "Projects Documentation", + "body": "Developer documentation project for the developer site.", + "number": 1, + "state": "open", + "creator": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "created_at": "2011-04-10T20:09:31Z", + "updated_at": "2014-03-03T18:58:10Z" + } +] \ No newline at end of file From 328f45fa4a53f5865c6897e50e717431bce2c98a Mon Sep 17 00:00:00 2001 From: gabriele Date: Tue, 22 Aug 2023 08:50:11 +0200 Subject: [PATCH 2/5] fixing doc tests --- src/api/projects.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/api/projects.rs b/src/api/projects.rs index ba45aa2a..4da43c8f 100644 --- a/src/api/projects.rs +++ b/src/api/projects.rs @@ -54,12 +54,12 @@ impl<'octo> ProjectHandler<'octo> { /// /// ```no_run /// # async fn run() -> octocrab::Result<()> { - /// let body = serde_json::json!({ "name": "Week One Sprint", "state": "open" }) + /// let body = serde_json::json!({ "name": "Week One Sprint", "state": "open" }); /// let project_id: u32 = 1002604; /// let project = octocrab::instance() /// .projects() /// .update_project(project_id) - /// .body(body) + /// .body(&body) /// .send() /// .await?; /// # Ok(()) @@ -102,7 +102,7 @@ impl<'octo> ProjectHandler<'octo> { /// ```no_run /// # async fn run() -> octocrab::Result<()> { /// let username = "octocat"; - /// let description = "Project Overview" + /// let description = "Project Overview"; /// let project = octocrab::instance() /// .projects() /// .create_user_project(username) @@ -124,7 +124,7 @@ impl<'octo> ProjectHandler<'octo> { /// /// ```no_run /// # async fn run() -> octocrab::Result<()> { - /// let username = "octocat" + /// let username = "octocat"; /// let project = octocrab::instance() /// .projects() /// .list_user_projects(username) @@ -147,15 +147,15 @@ impl<'octo> ProjectHandler<'octo> { /// * `org` - name of the organization /// /// ```no_run - /// # async fn run() -> octocrab::Result<()> - /// let org = "octocrab" + /// # async fn run() -> octocrab::Result<()> { + /// let org = "octocrab"; /// let projects = octocrab::instance() /// .projects() /// .list_organization_projects(org) /// .state("all") /// .send() /// .await?; - /// # OK(()) + /// # Ok(()) /// # } /// ``` pub fn list_organization_projects( @@ -230,8 +230,8 @@ impl<'octo> ProjectHandler<'octo> { /// /// ```no_run /// # async fn run() -> octocrab::Result<()> { - /// let owner = "octocat" - /// let repo = "octocrab" + /// let owner = "octocat"; + /// let repo = "octocrab"; /// let tags = octocrab::instance() /// .projects() /// .list_repository_projects("owner", "repo") From 50835a561a6f0b3887e17a1be4aee3a2e19763d9 Mon Sep 17 00:00:00 2001 From: gabriele Date: Tue, 22 Aug 2023 12:03:17 +0200 Subject: [PATCH 3/5] fix doc tests pt2 --- src/api/projects.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/api/projects.rs b/src/api/projects.rs index 4da43c8f..5888d441 100644 --- a/src/api/projects.rs +++ b/src/api/projects.rs @@ -174,14 +174,14 @@ impl<'octo> ProjectHandler<'octo> { /// /// ```no_run /// # async fn run() -> octocrab::Result<()> { - /// let org = "octocrab", - /// let name = "Organization Roadmap" + /// let org = "octocrab"; + /// let name = "Organization Roadmap"; /// let project = octocrab::instance() /// .projects() /// .create_organization_project(org, name) /// .send() /// .await?; - /// # OK(()) + /// # Ok(()) /// # } /// ``` pub fn create_organization_project( @@ -201,8 +201,10 @@ impl<'octo> ProjectHandler<'octo> { /// /// ```no_run /// # async fn run() -> octocrab::Result<()> { - /// let owner = "octocat" - /// let repo = "octocrab" + /// let owner = "octocat"; + /// let repo = "octocrab"; + /// let name = "My Project"; + /// let description = "Project Overview"; /// let tags = octocrab::instance() /// .projects() /// .create_repository_project("owner", "repo") From 81e69d0e9ca59b6cbaeb78ff1eeb781a2c667f62 Mon Sep 17 00:00:00 2001 From: gabriele Date: Tue, 22 Aug 2023 12:07:21 +0200 Subject: [PATCH 4/5] fix doc string --- src/api/projects/projects.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/api/projects/projects.rs b/src/api/projects/projects.rs index 5e8b4feb..0eeb3319 100644 --- a/src/api/projects/projects.rs +++ b/src/api/projects/projects.rs @@ -133,7 +133,7 @@ impl<'octo, 'r> CreateUserProjectBuilder<'octo, 'r> { } } -/// Helper builder struct to list a user project given the username of the user. +/// Helper builder struct to list user projects given the username of the user. /// /// Used by [`Octocrab::projects`]. #[derive(serde::Serialize)] @@ -177,7 +177,7 @@ impl<'octo, 'r> ListUserProjectsBuilder<'octo, 'r> { /// Helper builder struct to get a paged list of an organization's projects. /// -/// Used by [`Octocrab::orgs`]. +/// Used by [`Octocrab::projects`]. #[derive(serde::Serialize)] pub struct ListOrgProjectsBuilder<'octo, 'r> { #[serde(skip)] @@ -231,7 +231,7 @@ impl<'octo, 'r> ListOrgProjectsBuilder<'octo, 'r> { /// Helper builder struct to create an organization project. /// -/// Used by [`Octocrab::orgs`]. +/// Used by [`Octocrab::projects`]. #[derive(serde::Serialize)] pub struct CreateOrgProjectsBuilder<'octo, 'r> { #[serde(skip)] @@ -266,7 +266,7 @@ impl<'octo, 'r> CreateOrgProjectsBuilder<'octo, 'r> { /// Helper builder struct to get a paged list of repository projects /// -/// Used by [`Octocrab::repos`]. +/// Used by [`Octocrab::projects`]. #[derive(serde::Serialize)] pub struct ListRepositoryProjectsBuilder<'octo, 'r> { #[serde(skip)] @@ -318,7 +318,7 @@ pub struct NotNamed; /// Helper builder struct to get create a repository project /// -/// Used by [`Octocrab::repos`]. +/// Used by [`Octocrab::projects`]. #[derive(serde::Serialize)] pub struct CreateRepositoryProjectsBuilder<'octo, 'r, S> { #[serde(skip)] From 5f98556ac6e6ded2b094c35636afbf9eb11470f8 Mon Sep 17 00:00:00 2001 From: gabriele Date: Tue, 22 Aug 2023 12:38:45 +0200 Subject: [PATCH 5/5] better test names --- tests/projects_org_list_projects_test.rs | 2 +- tests/projects_repo_create_project_test.rs | 2 +- tests/projects_repo_list_projects_test.rs | 2 +- tests/projects_user_create_project_test.rs | 2 +- tests/projects_user_list_projects_test.rs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/projects_org_list_projects_test.rs b/tests/projects_org_list_projects_test.rs index 29478c99..32620624 100644 --- a/tests/projects_org_list_projects_test.rs +++ b/tests/projects_org_list_projects_test.rs @@ -37,7 +37,7 @@ fn setup_octocrab(uri: &str) -> Octocrab { } #[tokio::test] -async fn should_list_page_with_projects() { +async fn should_list_org_projects() { let org_project: Vec = serde_json::from_str(include_str!("resources/projects.json")).unwrap(); let owner = org_project[0].creator.login.clone(); diff --git a/tests/projects_repo_create_project_test.rs b/tests/projects_repo_create_project_test.rs index d5145451..9edb7856 100644 --- a/tests/projects_repo_create_project_test.rs +++ b/tests/projects_repo_create_project_test.rs @@ -36,7 +36,7 @@ fn setup_octocrab(uri: &str) -> Octocrab { } #[tokio::test] -async fn should_create_org_project() { +async fn should_create_repo_project() { let repo_project: Project = serde_json::from_str(include_str!("resources/project.json")).unwrap(); diff --git a/tests/projects_repo_list_projects_test.rs b/tests/projects_repo_list_projects_test.rs index 88c4c27b..7bf45fe1 100644 --- a/tests/projects_repo_list_projects_test.rs +++ b/tests/projects_repo_list_projects_test.rs @@ -39,7 +39,7 @@ fn setup_octocrab(uri: &str) -> Octocrab { } #[tokio::test] -async fn should_list_org_projects() { +async fn should_list_repo_projects() { let repo_project: Vec = serde_json::from_str(include_str!("resources/projects.json")).unwrap(); diff --git a/tests/projects_user_create_project_test.rs b/tests/projects_user_create_project_test.rs index 94380d80..75b963a0 100644 --- a/tests/projects_user_create_project_test.rs +++ b/tests/projects_user_create_project_test.rs @@ -35,7 +35,7 @@ fn setup_octocrab(uri: &str) -> Octocrab { } #[tokio::test] -async fn should_update_project_name() { +async fn should_create_user_project() { let org_project: Project = serde_json::from_str(include_str!("resources/project.json")).unwrap(); diff --git a/tests/projects_user_list_projects_test.rs b/tests/projects_user_list_projects_test.rs index 09e7b816..ad973a51 100644 --- a/tests/projects_user_list_projects_test.rs +++ b/tests/projects_user_list_projects_test.rs @@ -37,7 +37,7 @@ fn setup_octocrab(uri: &str) -> Octocrab { } #[tokio::test] -async fn should_get_projects_by_its_id() { +async fn should_list_user_projects() { let org_project: Vec = serde_json::from_str(include_str!("resources/user_projects.json")).unwrap();