From 61288e8f49baeccf650b2e3263b43cdbc846548e Mon Sep 17 00:00:00 2001 From: Lucien Cartier-Tilet Date: Tue, 31 Mar 2026 13:57:32 +0200 Subject: [PATCH] refactor(workflow): remove unnecessary async declarations --- src/prompts/prompter.rs | 2 +- src/prompts/workflow.rs | 138 ++++++++++++++++++---------------------- 2 files changed, 64 insertions(+), 76 deletions(-) diff --git a/src/prompts/prompter.rs b/src/prompts/prompter.rs index b507eb2..1367424 100644 --- a/src/prompts/prompter.rs +++ b/src/prompts/prompter.rs @@ -17,7 +17,7 @@ use crate::{ /// /// Implement this trait to supply a custom front-end (interactive TUI, mock, /// headless, etc.) to [`CommitWorkflow`](super::CommitWorkflow). -pub trait Prompter: Send + Sync { +pub trait Prompter { /// Prompt the user to select a commit type fn select_commit_type(&self) -> Result; diff --git a/src/prompts/workflow.rs b/src/prompts/workflow.rs index 597acde..1d21371 100644 --- a/src/prompts/workflow.rs +++ b/src/prompts/workflow.rs @@ -58,16 +58,13 @@ impl CommitWorkflow { if !self.executor.is_repository().await? { return Err(Error::NotARepository); } - let commit_type = self.type_selection().await?; + let commit_type = self.type_selection()?; loop { - let scope = self.scope_input().await?; - let description = self.description_input().await?; - let breaking_change = self.breaking_change_input().await?; - let body = self.body_input().await?; - match self - .preview_and_confirm(commit_type, scope, description, breaking_change, body) - .await - { + let scope = self.scope_input()?; + let description = self.description_input()?; + let breaking_change = self.breaking_change_input()?; + let body = self.body_input()?; + match self.preview_and_confirm(commit_type, scope, description, breaking_change, body) { Ok(conventional_commit) => { self.executor .describe(&conventional_commit.to_string()) @@ -86,7 +83,7 @@ impl CommitWorkflow { } /// Prompt user to select a commit type from the 11 available options - async fn type_selection(&self) -> Result { + fn type_selection(&self) -> Result { self.prompts.select_commit_type() } @@ -94,7 +91,7 @@ impl CommitWorkflow { /// /// Returns Ok(Scope) with the validated scope, or /// Error::Cancelled if user cancels - async fn scope_input(&self) -> Result { + fn scope_input(&self) -> Result { self.prompts.input_scope() } @@ -102,7 +99,7 @@ impl CommitWorkflow { /// /// Returns Ok(Description) with the validated description, or /// Error::Cancelled if user cancels - async fn description_input(&self) -> Result { + fn description_input(&self) -> Result { self.prompts.input_description() } @@ -110,12 +107,12 @@ impl CommitWorkflow { /// /// Returns Ok(BreakingChange) with the validated breaking change, /// or Error::Cancel if user cancels - async fn breaking_change_input(&self) -> Result { + fn breaking_change_input(&self) -> Result { self.prompts.input_breaking_change() } /// Prompt user to optionally add a free-form body via an external editor - async fn body_input(&self) -> Result { + fn body_input(&self) -> Result { self.prompts.input_body() } @@ -123,7 +120,7 @@ impl CommitWorkflow { /// /// This method also validates that the complete first line /// doesn't exceed 72 characters - async fn preview_and_confirm( + fn preview_and_confirm( &self, commit_type: CommitType, scope: Scope, @@ -224,46 +221,46 @@ mod tests { } /// Test that type_selection returns a valid CommitType - #[tokio::test] - async fn type_selection_returns_valid_type() { + #[test] + fn type_selection_returns_valid_type() { // Updated to use mock prompts to avoid TUI hanging let mock_executor = MockJjExecutor::new(); let mock_prompts = MockPrompts::new().with_commit_type(CommitType::Feat); let workflow = CommitWorkflow::with_prompts(mock_executor, mock_prompts); // Now we can actually test the method with mock prompts - let result = workflow.type_selection().await; + let result = workflow.type_selection(); assert!(result.is_ok()); assert_eq!(result.unwrap(), CommitType::Feat); } /// Test that scope_input returns a valid Scope - #[tokio::test] - async fn scope_input_returns_valid_scope() { + #[test] + fn scope_input_returns_valid_scope() { let mock_executor = MockJjExecutor::new(); let mock_prompts = MockPrompts::new().with_scope(Scope::parse("test").unwrap()); let workflow = CommitWorkflow::with_prompts(mock_executor, mock_prompts); - let result = workflow.scope_input().await; + let result = workflow.scope_input(); assert!(result.is_ok()); assert_eq!(result.unwrap(), Scope::parse("test").unwrap()); } /// Test that description_input returns a valid Description - #[tokio::test] - async fn description_input_returns_valid_description() { + #[test] + fn description_input_returns_valid_description() { let mock_executor = MockJjExecutor::new(); let mock_prompts = MockPrompts::new().with_description(Description::parse("test").unwrap()); let workflow = CommitWorkflow::with_prompts(mock_executor, mock_prompts); - let result = workflow.description_input().await; + let result = workflow.description_input(); assert!(result.is_ok()); assert_eq!(result.unwrap(), Description::parse("test").unwrap()); } /// Test that preview_and_confirm returns a ConventionalCommit - #[tokio::test] - async fn preview_and_confirm_returns_conventional_commit() { + #[test] + fn preview_and_confirm_returns_conventional_commit() { let mock_executor = MockJjExecutor::new(); let mock_prompts = MockPrompts::new().with_confirm(true); let workflow = CommitWorkflow::with_prompts(mock_executor, mock_prompts); @@ -273,9 +270,8 @@ mod tests { let description = Description::parse("test description").unwrap(); let breaking_change = BreakingChange::No; let body = Body::default(); - let result = workflow - .preview_and_confirm(commit_type, scope, description, breaking_change, body) - .await; + let result = + workflow.preview_and_confirm(commit_type, scope, description, breaking_change, body); assert!(result.is_ok()); } @@ -451,8 +447,8 @@ mod tests { } /// Test that mock prompts track method calls correctly - #[tokio::test] - async fn test_mock_prompts_track_calls() { + #[test] + fn test_mock_prompts_track_calls() { let mock_executor = MockJjExecutor::new().with_is_repo_response(Ok(true)); let mock_prompts = MockPrompts::new() .with_commit_type(CommitType::Feat) @@ -552,21 +548,19 @@ mod tests { /// BreakingChange::No was hard-coded, so a confirmed /// breaking-change commit was silently applied without the '!' /// marker. - #[tokio::test] - async fn preview_and_confirm_forwards_breaking_change_yes() { + #[test] + fn preview_and_confirm_forwards_breaking_change_yes() { let mock_executor = MockJjExecutor::new(); let mock_prompts = MockPrompts::new().with_confirm(true); let workflow = CommitWorkflow::with_prompts(mock_executor, mock_prompts); - let result = workflow - .preview_and_confirm( - CommitType::Feat, - Scope::empty(), - Description::parse("remove old API").unwrap(), - BreakingChange::Yes, - Body::default(), - ) - .await; + let result = workflow.preview_and_confirm( + CommitType::Feat, + Scope::empty(), + Description::parse("remove old API").unwrap(), + BreakingChange::Yes, + Body::default(), + ); assert!(result.is_ok(), "expected Ok, got: {:?}", result); let message = result.unwrap().to_string(); @@ -580,22 +574,20 @@ mod tests { /// Preview_and_confirm must forward BreakingChange::WithNote, /// producing a commit with both the '!' header marker and the /// BREAKING CHANGE footer. - #[tokio::test] - async fn preview_and_confirm_forwards_breaking_change_with_note() { + #[test] + fn preview_and_confirm_forwards_breaking_change_with_note() { let mock_executor = MockJjExecutor::new(); let mock_prompts = MockPrompts::new().with_confirm(true); let workflow = CommitWorkflow::with_prompts(mock_executor, mock_prompts); let breaking_change: BreakingChange = "removes legacy endpoint".into(); - let result = workflow - .preview_and_confirm( - CommitType::Feat, - Scope::empty(), - Description::parse("drop legacy API").unwrap(), - breaking_change, - Body::default(), - ) - .await; + let result = workflow.preview_and_confirm( + CommitType::Feat, + Scope::empty(), + Description::parse("drop legacy API").unwrap(), + breaking_change, + Body::default(), + ); assert!(result.is_ok(), "expected Ok, got: {:?}", result); let message = result.unwrap().to_string(); @@ -655,21 +647,19 @@ mod tests { /// /// Currently the implementation passes Body::default() instead of the /// received body, so this test will fail until that is fixed. - #[tokio::test] - async fn preview_and_confirm_forwards_body() { + #[test] + fn preview_and_confirm_forwards_body() { let mock_executor = MockJjExecutor::new(); let mock_prompts = MockPrompts::new().with_confirm(true); let workflow = CommitWorkflow::with_prompts(mock_executor, mock_prompts); - let result = workflow - .preview_and_confirm( - CommitType::Feat, - Scope::empty(), - Description::parse("add feature").unwrap(), - BreakingChange::No, - Body::from("This explains the change."), - ) - .await; + let result = workflow.preview_and_confirm( + CommitType::Feat, + Scope::empty(), + Description::parse("add feature").unwrap(), + BreakingChange::No, + Body::from("This explains the change."), + ); assert!(result.is_ok(), "expected Ok, got: {:?}", result); assert!( @@ -684,21 +674,19 @@ mod tests { /// preview_and_confirm must forward the body even when a breaking change is present /// /// Expected format: "type!: desc\n\nbody\n\nBREAKING CHANGE: note" - #[tokio::test] - async fn preview_and_confirm_forwards_body_with_breaking_change() { + #[test] + fn preview_and_confirm_forwards_body_with_breaking_change() { let mock_executor = MockJjExecutor::new(); let mock_prompts = MockPrompts::new().with_confirm(true); let workflow = CommitWorkflow::with_prompts(mock_executor, mock_prompts); - let result = workflow - .preview_and_confirm( - CommitType::Feat, - Scope::empty(), - Description::parse("drop legacy API").unwrap(), - "removes legacy endpoint".into(), - Body::from("The endpoint was deprecated in v2."), - ) - .await; + let result = workflow.preview_and_confirm( + CommitType::Feat, + Scope::empty(), + Description::parse("drop legacy API").unwrap(), + "removes legacy endpoint".into(), + Body::from("The endpoint was deprecated in v2."), + ); assert!(result.is_ok(), "expected Ok, got: {:?}", result); let message = result.unwrap().to_string();