From fb03f2f9d86b1ff8ea8a295133933a9703e32898 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 11 Mar 2025 13:16:53 +0100 Subject: [PATCH 01/13] tests: use `mod tests` for inline testing modules --- ghostflow-github/src/client.rs | 2 +- ghostflow-github/src/ghostflow.rs | 2 +- ghostflow-gitlab/src/lib.rs | 2 +- ghostflow/src/utils/template_string.rs | 2 +- ghostflow/src/utils/trailer.rs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ghostflow-github/src/client.rs b/ghostflow-github/src/client.rs index 45a2dcd5..2d26618b 100644 --- a/ghostflow-github/src/client.rs +++ b/ghostflow-github/src/client.rs @@ -373,7 +373,7 @@ where } #[cfg(test)] -mod test { +mod tests { use reqwest::{Client, StatusCode}; use crate::client::{retry_with_backoff, Github, GithubError, BACKOFF_LIMIT}; diff --git a/ghostflow-github/src/ghostflow.rs b/ghostflow-github/src/ghostflow.rs index 253735e8..1b606a79 100644 --- a/ghostflow-github/src/ghostflow.rs +++ b/ghostflow-github/src/ghostflow.rs @@ -1394,7 +1394,7 @@ impl Debug for GithubService { } #[cfg(test)] -mod test { +mod tests { #[test] fn test_github_trim() { use super::{ diff --git a/ghostflow-gitlab/src/lib.rs b/ghostflow-gitlab/src/lib.rs index af9ade74..b767faf3 100644 --- a/ghostflow-gitlab/src/lib.rs +++ b/ghostflow-gitlab/src/lib.rs @@ -1005,7 +1005,7 @@ impl fmt::Debug for GitlabService { } #[cfg(test)] -mod test { +mod tests { #[test] fn test_mr_update_re() { let comments = [ diff --git a/ghostflow/src/utils/template_string.rs b/ghostflow/src/utils/template_string.rs index fba24268..9707dd8e 100644 --- a/ghostflow/src/utils/template_string.rs +++ b/ghostflow/src/utils/template_string.rs @@ -129,7 +129,7 @@ impl Debug for TemplateString { } #[cfg(test)] -mod test { +mod tests { use std::borrow::Cow; use super::{TemplatePart, TemplateString}; diff --git a/ghostflow/src/utils/trailer.rs b/ghostflow/src/utils/trailer.rs index 5081071e..94c085b4 100644 --- a/ghostflow/src/utils/trailer.rs +++ b/ghostflow/src/utils/trailer.rs @@ -136,7 +136,7 @@ impl Display for Trailer { } #[cfg(test)] -mod test { +mod tests { use crate::utils::TrailerRef; fn check_content(content: &str, expected: &[(&str, &str)]) { -- GitLab From 26d3bd5bcedbd845fe3cfea48f7c78320f18b6ae Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 11 Mar 2025 13:17:08 +0100 Subject: [PATCH 02/13] gitlab: add tests for `User::for_domain` --- ghostflow-gitlab/src/types.rs | 49 +++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/ghostflow-gitlab/src/types.rs b/ghostflow-gitlab/src/types.rs index 43724f34..24339e0d 100644 --- a/ghostflow-gitlab/src/types.rs +++ b/ghostflow-gitlab/src/types.rs @@ -238,3 +238,52 @@ pub struct PipelineJob { pub struct ImpersonationToken { pub token: String, } + +#[cfg(test)] +mod tests { + use crate::types::{FullUser, User}; + + #[test] + fn test_user_for_domain() { + let expect_username = "uname"; + let expect_email = "foo@bar.invalid"; + let expect_name = "name"; + let user = User { + username: expect_username.into(), + email: Some(expect_email.into()), + name: expect_name.into(), + id: 0, + }; + + let FullUser { + username, + email, + name, + } = user.for_domain("unused"); + assert_eq!(username, expect_username); + assert_eq!(email, expect_email); + assert_eq!(name, expect_name); + } + + #[test] + fn test_user_for_domain_defaulted() { + let expect_username = "uname"; + let expect_name = "name"; + let user = User { + username: expect_username.into(), + email: None, + name: expect_name.into(), + id: 0, + }; + + let expect_email = "uname@users.domain"; + let FullUser { + username, + email, + name, + } = user.for_domain("domain"); + assert_eq!(username, expect_username); + assert_eq!(email, expect_email); + assert_eq!(name, expect_name); + } +} -- GitLab From b09327a7d11e0f04ce2b10a7b6adfbee6e050d2e Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 11 Mar 2025 13:21:19 +0100 Subject: [PATCH 03/13] github: remove `machine-man-preview` accept header The preview is over and is no longer necessary. --- ghostflow-github/src/authorization.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/ghostflow-github/src/authorization.rs b/ghostflow-github/src/authorization.rs index fb4de836..7404982e 100644 --- a/ghostflow-github/src/authorization.rs +++ b/ghostflow-github/src/authorization.rs @@ -135,13 +135,6 @@ impl GithubAppAuth { header::ACCEPT, "application/vnd.github.v3+json".parse().unwrap(), ), - // GitHub App installations - ( - header::ACCEPT, - "application/vnd.github.machine-man-preview+json" - .parse() - .unwrap(), - ), ] .iter() .cloned() -- GitLab From 70e5993d731287b6a38011ae61ca1749082e9685 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 11 Mar 2025 13:21:39 +0100 Subject: [PATCH 04/13] github: use `HeaderValue::from_static` This removes a literal `unwrap()` from the code (it is done internally in `from_static` though). --- ghostflow-github/src/authorization.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ghostflow-github/src/authorization.rs b/ghostflow-github/src/authorization.rs index 7404982e..ff2af8f1 100644 --- a/ghostflow-github/src/authorization.rs +++ b/ghostflow-github/src/authorization.rs @@ -13,7 +13,7 @@ use chrono::{DateTime, Duration, Utc}; use jsonwebtoken::{Algorithm, EncodingKey, Header}; use log::error; use reqwest::blocking::Client; -use reqwest::header::{self, HeaderMap}; +use reqwest::header::{self, HeaderMap, HeaderValue}; use reqwest::Url; use serde::{Deserialize, Serialize}; use thiserror::Error; @@ -133,7 +133,7 @@ impl GithubAppAuth { // GitHub v3 API ( header::ACCEPT, - "application/vnd.github.v3+json".parse().unwrap(), + HeaderValue::from_static("application/vnd.github.v3+json"), ), ] .iter() -- GitLab From 6e0b28de02627030713316a6b9b477fd4b8d5370 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 11 Mar 2025 13:48:19 +0100 Subject: [PATCH 05/13] testing: use a lower `BACKOFF_LIMIT` when testing It still tests the behavior but doesn't cause huge delays. --- ghostflow-github/src/client.rs | 2 +- ghostflow-gitlab/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ghostflow-github/src/client.rs b/ghostflow-github/src/client.rs index 2d26618b..be43e2b5 100644 --- a/ghostflow-github/src/client.rs +++ b/ghostflow-github/src/client.rs @@ -23,7 +23,7 @@ use thiserror::Error; use crate::authorization::{CurrentUser, GithubAuthError, GithubAuthorization}; // The maximum number of times we will retry server errors. -const BACKOFF_LIMIT: usize = 5; +const BACKOFF_LIMIT: usize = if cfg!(test) { 2 } else { 5 }; // The number of seconds to start retries at. const BACKOFF_START: Duration = Duration::from_secs(1); // How much to scale retry timeouts for a single query. diff --git a/ghostflow-gitlab/src/lib.rs b/ghostflow-gitlab/src/lib.rs index b767faf3..2db0dfb8 100644 --- a/ghostflow-gitlab/src/lib.rs +++ b/ghostflow-gitlab/src/lib.rs @@ -37,7 +37,7 @@ enum Retry { } // The maximum number of times we will retry server errors. -const BACKOFF_LIMIT: usize = 5; +const BACKOFF_LIMIT: usize = if cfg!(test) { 2 } else { 5 }; // The number of seconds to start retries at. const BACKOFF_START: Duration = Duration::from_secs(1); // How much to scale retry timeouts for a single query. -- GitLab From d608e311fce70b1469d82d9b0f4471f978adfd6c Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 11 Mar 2025 13:48:53 +0100 Subject: [PATCH 06/13] gitlab: improve commit status state conversion function names --- ghostflow-gitlab/src/lib.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ghostflow-gitlab/src/lib.rs b/ghostflow-gitlab/src/lib.rs index 2db0dfb8..b1a09897 100644 --- a/ghostflow-gitlab/src/lib.rs +++ b/ghostflow-gitlab/src/lib.rs @@ -132,7 +132,9 @@ fn ghostflow_pipeline_state(status: types::PipelineStatus) -> PipelineState { } } -fn gitlab_state(state: CommitStatusState) -> api::projects::repository::commits::CommitStatusState { +fn gitlab_commit_status_state( + state: CommitStatusState, +) -> api::projects::repository::commits::CommitStatusState { match state { CommitStatusState::Pending => { api::projects::repository::commits::CommitStatusState::Pending @@ -147,7 +149,7 @@ fn gitlab_state(state: CommitStatusState) -> api::projects::repository::commits: } } -fn ghostflow_state(state: types::StatusState) -> CommitStatusState { +fn ghostflow_commit_status_state(state: types::StatusState) -> CommitStatusState { match state { types::StatusState::Manual | types::StatusState::Skipped @@ -711,7 +713,7 @@ impl HostingService for GitlabService { .into_iter() .map(move |status: types::CommitStatus| { CommitStatus { - state: ghostflow_state(status.status), + state: ghostflow_commit_status_state(status.status), author: ghostflow_user(status.author.for_domain(self.domain)), refname: status.ref_, name: status.name, @@ -741,7 +743,7 @@ impl HostingService for GitlabService { builder .project(status.commit.repo.name.as_str()) .commit(status.commit.id.as_str()) - .state(gitlab_state(status.state)) + .state(gitlab_commit_status_state(status.state)) .name(status.name) .description(status.description); -- GitLab From 9468a8b1b76f57051c3214da76ed345c8dadace6 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 11 Mar 2025 13:49:08 +0100 Subject: [PATCH 07/13] github: update test function names to match patterns --- ghostflow-github/src/client.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ghostflow-github/src/client.rs b/ghostflow-github/src/client.rs index be43e2b5..8ccfd74c 100644 --- a/ghostflow-github/src/client.rs +++ b/ghostflow-github/src/client.rs @@ -379,7 +379,7 @@ mod tests { use crate::client::{retry_with_backoff, Github, GithubError, BACKOFF_LIMIT}; #[test] - fn backoff_first_success() { + fn test_retry_with_backoff_first_success() { let mut call_count = 0; retry_with_backoff(|| { call_count += 1; @@ -390,7 +390,7 @@ mod tests { } #[test] - fn backoff_second_success() { + fn test_retry_with_backoff_second_success() { let mut call_count = 0; let mut did_err = false; retry_with_backoff(|| { @@ -409,7 +409,7 @@ mod tests { } #[test] - fn backoff_no_success() { + fn test_retry_with_backoff_no_success() { let mut call_count = 0; let err = retry_with_backoff::<_, ()>(|| { call_count += 1; @@ -426,7 +426,7 @@ mod tests { } #[test] - fn ensure_rest_headers_work() { + fn test_rest_headers_work() { let req = Client::new() .post("https://nowhere") .headers(Github::rest_accept_headers()) @@ -446,7 +446,7 @@ mod tests { } #[test] - fn ensure_graphql_headers_work() { + fn test_graphql_headers_work() { let req = Client::new() .post("https://nowhere") .headers(Github::gql_accept_headers()) -- GitLab From 9e3aa34abb5e846e7c864f5e15cda75f813357a3 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 11 Mar 2025 13:50:14 +0100 Subject: [PATCH 08/13] gitlab: test backoff behavior --- ghostflow-gitlab/src/lib.rs | 77 +++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/ghostflow-gitlab/src/lib.rs b/ghostflow-gitlab/src/lib.rs index b1a09897..212fc0aa 100644 --- a/ghostflow-gitlab/src/lib.rs +++ b/ghostflow-gitlab/src/lib.rs @@ -1008,6 +1008,83 @@ impl fmt::Debug for GitlabService { #[cfg(test)] mod tests { + use gitlab::api; + use http::StatusCode; + use thiserror::Error; + + #[derive(Debug, Error)] + enum MyError {} + + fn mk_gitlab_status(status: StatusCode) -> api::ApiError { + api::ApiError::::GitlabWithStatus { + status, + msg: String::new(), + } + } + + type TestResult = Result<(), api::ApiError>; + + #[test] + fn test_should_backoff() { + let items = [ + (mk_gitlab_status(StatusCode::NOT_FOUND), true), + (mk_gitlab_status(StatusCode::FORBIDDEN), false), + ]; + + for (i, e) in items { + assert_eq!(super::should_backoff(&i), e); + } + } + + #[test] + fn test_retry_with_backoff_first_success() { + let mut call_count = 0; + super::retry_with_backoff(|| -> TestResult { + call_count += 1; + Ok(()) + }) + .unwrap(); + assert_eq!(call_count, 1); + } + + #[test] + fn test_retry_with_backoff_second_success() { + let mut call_count = 0; + let mut did_err = false; + super::retry_with_backoff(|| { + call_count += 1; + if did_err { + Ok(()) + } else { + did_err = true; + Err(mk_gitlab_status(StatusCode::NOT_FOUND)) + } + }) + .unwrap(); + assert_eq!(call_count, 2); + } + + #[test] + fn test_retry_with_backoff_no_success() { + let mut call_count = 0; + let err = super::retry_with_backoff(|| -> TestResult { + call_count += 1; + Err(mk_gitlab_status(StatusCode::NOT_FOUND)) + }) + .unwrap_err(); + assert_eq!(call_count, super::BACKOFF_LIMIT); + if let api::ApiError::GitlabWithStatus { + status, + msg, + } = err + { + assert_eq!(status, StatusCode::NOT_FOUND); + assert_eq!(msg, "failed even after exponential backoff"); + } else { + panic!("unexpected error: {}", err); + } + } + #[test] fn test_mr_update_re() { let comments = [ -- GitLab From 21477e39c68059868956aecb406ef6b153486733 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 11 Mar 2025 13:50:34 +0100 Subject: [PATCH 09/13] gitlab: test ghostflow/gitlab conversion functions --- ghostflow-gitlab/src/lib.rs | 98 +++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/ghostflow-gitlab/src/lib.rs b/ghostflow-gitlab/src/lib.rs index 212fc0aa..1b3809f3 100644 --- a/ghostflow-gitlab/src/lib.rs +++ b/ghostflow-gitlab/src/lib.rs @@ -1008,10 +1008,13 @@ impl fmt::Debug for GitlabService { #[cfg(test)] mod tests { + use ghostflow::host::{CommitStatusState, PipelineState, User}; use gitlab::api; use http::StatusCode; use thiserror::Error; + use crate::types; + #[derive(Debug, Error)] enum MyError {} @@ -1121,4 +1124,99 @@ mod tests { assert!(super::mr_update_re().is_match(dbg!(comment))); } } + + #[test] + fn test_ghostflow_user() { + let expect_username = "uname"; + let expect_email = "foo@bar.invalid"; + let expect_name = "name"; + let full_user = types::FullUser { + username: expect_username.into(), + email: expect_email.into(), + name: expect_name.into(), + }; + + let User { + handle, + name, + email, + } = super::ghostflow_user(full_user); + assert_eq!(handle, expect_username); + assert_eq!(email, expect_email); + assert_eq!(name, expect_name); + } + + #[test] + fn test_ghostflow_pipeline_state() { + let items = [ + (types::PipelineStatus::Created, PipelineState::InProgress), + ( + types::PipelineStatus::WaitingForResource, + PipelineState::InProgress, + ), + (types::PipelineStatus::Preparing, PipelineState::InProgress), + ( + types::PipelineStatus::WaitingForCallback, + PipelineState::InProgress, + ), + (types::PipelineStatus::Pending, PipelineState::InProgress), + (types::PipelineStatus::Running, PipelineState::InProgress), + (types::PipelineStatus::Failed, PipelineState::Failed), + (types::PipelineStatus::Success, PipelineState::Success), + (types::PipelineStatus::Canceling, PipelineState::Canceled), + (types::PipelineStatus::Canceled, PipelineState::Canceled), + (types::PipelineStatus::Skipped, PipelineState::Canceled), + (types::PipelineStatus::Manual, PipelineState::Manual), + (types::PipelineStatus::Scheduled, PipelineState::InProgress), + ]; + + for (gl, gf) in items { + assert_eq!(super::ghostflow_pipeline_state(gl), gf); + } + } + + #[test] + fn test_gitlab_status_state() { + let items = [ + ( + CommitStatusState::Pending, + api::projects::repository::commits::CommitStatusState::Pending, + ), + ( + CommitStatusState::Success, + api::projects::repository::commits::CommitStatusState::Success, + ), + ( + CommitStatusState::Failed, + api::projects::repository::commits::CommitStatusState::Failed, + ), + ( + CommitStatusState::Running, + api::projects::repository::commits::CommitStatusState::Running, + ), + ]; + + for (gf, gl) in items { + assert_eq!(super::gitlab_commit_status_state(gf), gl); + } + } + + #[test] + fn test_ghostflow_commit_status_state() { + let items = [ + (types::StatusState::Created, CommitStatusState::Pending), + (types::StatusState::Pending, CommitStatusState::Pending), + (types::StatusState::Running, CommitStatusState::Running), + (types::StatusState::Success, CommitStatusState::Success), + (types::StatusState::Failed, CommitStatusState::Failed), + (types::StatusState::Canceled, CommitStatusState::Pending), + (types::StatusState::Skipped, CommitStatusState::Pending), + (types::StatusState::Manual, CommitStatusState::Pending), + (types::StatusState::Scheduled, CommitStatusState::Pending), + ]; + + for (gl, gf) in items { + assert_eq!(super::ghostflow_commit_status_state(gl), gf); + } + } } -- GitLab From 7a3f87c23b5701354fb62e5bc418b25677a72da1 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 11 Mar 2025 14:14:27 +0100 Subject: [PATCH 10/13] gitlab: test Reference* types --- ghostflow-gitlab/src/lib.rs | 149 ++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) diff --git a/ghostflow-gitlab/src/lib.rs b/ghostflow-gitlab/src/lib.rs index 1b3809f3..b485fe4f 100644 --- a/ghostflow-gitlab/src/lib.rs +++ b/ghostflow-gitlab/src/lib.rs @@ -1008,6 +1008,8 @@ impl fmt::Debug for GitlabService { #[cfg(test)] mod tests { + use std::collections::BTreeMap; + use ghostflow::host::{CommitStatusState, PipelineState, User}; use gitlab::api; use http::StatusCode; @@ -1015,6 +1017,8 @@ mod tests { use crate::types; + use super::{ReferenceLevel, ReferenceTarget}; + #[derive(Debug, Error)] enum MyError {} @@ -1219,4 +1223,149 @@ mod tests { assert_eq!(super::ghostflow_commit_status_state(gl), gf); } } + + #[test] + fn test_reference_target_issue() { + let issue = types::Issue { + labels: Vec::new(), + project_id: 0, + web_url: String::new(), + iid: 100, + }; + + assert_eq!(types::Issue::sigil(), '#'); + assert_eq!(issue.id(), 100); + } + + #[test] + fn test_reference_target_merge_request() { + let mr = types::MergeRequest { + source_project_id: 0, + source_branch: String::new(), + target_branch: String::new(), + description: None, + sha: None, + work_in_progress: false, + force_remove_source_branch: None, + author: types::Author { + id: 0, + }, + web_url: String::new(), + iid: 100, + }; + + assert_eq!(types::MergeRequest::sigil(), '!'); + assert_eq!(mr.id(), 100); + } + + #[test] + fn test_reference_level_default() { + assert_eq!(ReferenceLevel::default(), ReferenceLevel::Project); + } + + #[test] + fn test_reference_level_between() { + let namespaces: BTreeMap<&'static str, u64> = [("group", 100), ("other_group", 101)] + .iter() + .cloned() + .collect(); + let projects: BTreeMap<&'static str, u64> = [ + ("project", 200), + ("sibling_project", 201), + ("other_project", 202), + ] + .iter() + .cloned() + .collect(); + let mk_project = |namespace: &str, project: &str| { + types::Project { + id: *projects.get(project).unwrap(), + path_with_namespace: format!("{}/{}", namespace, project), + ssh_url_to_repo: String::new(), + http_url_to_repo: String::new(), + forked_from_project: None, + namespace: types::Namespace { + id: *namespaces.get(namespace).unwrap(), + kind: types::NamespaceKind::Group, + path: namespace.into(), + }, + path: project.into(), + builds_access_level: types::AccessLevel::Disabled, + } + }; + + let project_source = mk_project("group", "project"); + let project_target_same = mk_project("group", "project"); + let project_target_sibling = mk_project("group", "sibling_project"); + let project_target_elsewhere = mk_project("other_group", "other_project"); + + let items = [ + (&project_source, ReferenceLevel::Project), + (&project_target_same, ReferenceLevel::Project), + (&project_target_sibling, ReferenceLevel::Namespace), + (&project_target_elsewhere, ReferenceLevel::Site), + ]; + + for (p, rl) in items { + assert_eq!(ReferenceLevel::between(&project_source, p), rl); + } + } + + #[test] + fn test_reference_level_to() { + let project = types::Project { + id: 0, + path_with_namespace: "namespace/project".into(), + ssh_url_to_repo: String::new(), + http_url_to_repo: String::new(), + forked_from_project: None, + namespace: types::Namespace { + id: 0, + kind: types::NamespaceKind::Group, + path: "namespace".into(), + }, + path: "project".into(), + builds_access_level: types::AccessLevel::Disabled, + }; + let issue = types::Issue { + labels: Vec::new(), + project_id: 0, + web_url: String::new(), + iid: 100, + }; + let mr = types::MergeRequest { + source_project_id: 0, + source_branch: String::new(), + target_branch: String::new(), + description: None, + sha: None, + work_in_progress: false, + force_remove_source_branch: None, + author: types::Author { + id: 0, + }, + web_url: String::new(), + iid: 200, + }; + + let issue_items = [ + (ReferenceLevel::Project, "#100"), + (ReferenceLevel::Namespace, "project#100"), + (ReferenceLevel::Site, "namespace/project#100"), + ]; + + for (rl, expect) in issue_items { + assert_eq!(rl.to(&project, &issue), expect); + } + + let mr_items = [ + (ReferenceLevel::Project, "!200"), + (ReferenceLevel::Namespace, "project!200"), + (ReferenceLevel::Site, "namespace/project!200"), + ]; + + for (rl, expect) in mr_items { + assert_eq!(rl.to(&project, &mr), expect); + } + } } -- GitLab From 336af83e3001dfd391af55fb6f7c448fcc527fa5 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 11 Mar 2025 14:44:06 +0100 Subject: [PATCH 11/13] github: test some ghostflow conversion routines --- ghostflow-github/src/ghostflow.rs | 45 +++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/ghostflow-github/src/ghostflow.rs b/ghostflow-github/src/ghostflow.rs index 1b606a79..8a801551 100644 --- a/ghostflow-github/src/ghostflow.rs +++ b/ghostflow-github/src/ghostflow.rs @@ -1395,6 +1395,51 @@ impl Debug for GithubService { #[cfg(test)] mod tests { + use ghostflow::host::User; + + use crate::authorization::CurrentUser; + + #[test] + fn test_current_user_conversion() { + let expected_login = "login"; + let expected_email = "foo@bar.invalid"; + let expected_name = "name"; + let current_user = CurrentUser { + login: expected_login.into(), + email: expected_email.into(), + name: expected_name.into(), + }; + + let User { + handle, + email, + name, + } = current_user.into(); + assert_eq!(handle, expected_login); + assert_eq!(email, expected_email); + assert_eq!(name, expected_name); + } + + #[test] + fn test_pr_reactions() { + use crate::queries::pull_request_reactions::ReactionContent; + let items = [ + (ReactionContent::CONFUSED, "confused"), + (ReactionContent::EYES, "eyes"), + (ReactionContent::HEART, "heart"), + (ReactionContent::HOORAY, "hooray"), + (ReactionContent::LAUGH, "laugh"), + (ReactionContent::ROCKET, "rocket"), + (ReactionContent::THUMBS_DOWN, "-1"), + (ReactionContent::THUMBS_UP, "+1"), + (ReactionContent::Other("blah".into()), "blah"), + ]; + + for (r, s) in items { + assert_eq!(String::from(r), s); + } + } + #[test] fn test_github_trim() { use super::{ -- GitLab From 96b2052bed372dc196231f3698fae777b0857961 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 11 Mar 2025 14:44:18 +0100 Subject: [PATCH 12/13] github: test the set of request headers --- ghostflow-github/src/client.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/ghostflow-github/src/client.rs b/ghostflow-github/src/client.rs index 8ccfd74c..e228028e 100644 --- a/ghostflow-github/src/client.rs +++ b/ghostflow-github/src/client.rs @@ -374,10 +374,26 @@ where #[cfg(test)] mod tests { - use reqwest::{Client, StatusCode}; + use reqwest::{header, Client, StatusCode}; use crate::client::{retry_with_backoff, Github, GithubError, BACKOFF_LIMIT}; + #[test] + fn test_rest_accept_headers() { + let rest_headers = Github::rest_accept_headers(); + assert_eq!(rest_headers.len(), 1); + assert_eq!( + rest_headers.get(header::ACCEPT).unwrap(), + "application/vnd.github.v3+json", + ); + } + + #[test] + fn test_gql_accept_headers() { + let gql_headers = Github::gql_accept_headers(); + assert!(gql_headers.is_empty()); + } + #[test] fn test_retry_with_backoff_first_success() { let mut call_count = 0; -- GitLab From a67dfa6a8f5a5cfaa3e7352ec921d68efe5725fe Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Tue, 11 Mar 2025 14:44:28 +0100 Subject: [PATCH 13/13] github: fix test failure string --- ghostflow-github/src/client.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/ghostflow-github/src/client.rs b/ghostflow-github/src/client.rs index e228028e..77a9b168 100644 --- a/ghostflow-github/src/client.rs +++ b/ghostflow-github/src/client.rs @@ -453,10 +453,7 @@ mod tests { for (key, value) in Github::rest_accept_headers().iter() { if !headers.get_all(key).iter().any(|av| av == value) { - panic!( - "GraphQL request is missing HTTP header `{}: {:?}`", - key, value, - ); + panic!("REST request is missing HTTP header `{}: {:?}`", key, value); } } } -- GitLab