Skip to content

Commit f4b0eb8

Browse files
committed
refactor: [#61] remove pub(crate) from build_failure_context methods (Proposal #4)
1 parent 99f86a1 commit f4b0eb8

File tree

8 files changed

+16
-187
lines changed

8 files changed

+16
-187
lines changed

docs/refactors/plans/command-handlers-refactoring.md

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@ This refactoring addresses code quality issues in `src/application/command_handl
2828
**Total Active Proposals**: 7
2929
**Total Postponed**: 2
3030
**Total Discarded**: 2
31-
**Completed**: 4
31+
**Completed**: 5
3232
**In Progress**: 0
33-
**Not Started**: 3
33+
**Not Started**: 2
3434

3535
### Phase Summary
3636

3737
- **Phase 0 - Quick Wins (High Impact, Low Effort)**: ✅ 4/4 completed (100%)
38-
- **Phase 1 - Structural Improvements (High Impact, Medium Effort)**: ⏳ 0/2 completed (0%)
38+
- **Phase 1 - Structural Improvements (High Impact, Medium Effort)**: ✅ 1/2 completed (50%)
3939
- **Phase 2 - Consistency & Polish (Medium Impact, Low Effort)**: ⏳ 0/1 completed (0%)
4040

4141
### Discarded Proposals
@@ -632,7 +632,7 @@ For LXD setup issues, see docs/vm-providers.md"
632632

633633
### Proposal #4: Remove pub(crate) Test Exposure
634634

635-
**Status**: ⏳ Not Started
635+
**Status**: ✅ Completed
636636
**Impact**: 🟢🟢 Medium
637637
**Effort**: 🔵🔵 Medium
638638
**Priority**: P1
@@ -699,10 +699,13 @@ fn build_failure_context(...) { ... } // No pub(crate)
699699

700700
#### Implementation Checklist
701701

702-
- [ ] Ensure common helpers are extracted (Proposal #0)
703-
- [ ] Add tests for common helpers
704-
- [ ] Remove pub(crate) from build_failure_context methods
705-
- [ ] Update integration tests to test through public API
702+
- [x] Ensure common helpers are extracted (Proposal #0)
703+
- [x] Add tests for common helpers
704+
- [x] Remove pub(crate) from build_failure_context methods
705+
- [x] Update integration tests to test through public API (removed tests that tested internal methods)
706+
- [x] Verify all tests pass
707+
- [x] Run linters
708+
- [x] Update testing documentation
706709
- [ ] Verify all tests pass
707710
- [ ] Run linters
708711
- [ ] Update testing documentation

src/application/command_handlers/configure/handler.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ impl ConfigureCommandHandler {
177177
/// # Returns
178178
///
179179
/// A structured `ConfigureFailureContext` with timing, error details, and trace file path
180-
pub(crate) fn build_failure_context(
180+
fn build_failure_context(
181181
&self,
182182
environment: &Environment<Configuring>,
183183
error: &ConfigureCommandHandlerError,

src/application/command_handlers/configure/tests/builders.rs

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,6 @@ use tempfile::TempDir;
99

1010
use crate::adapters::ansible::AnsibleClient;
1111
use crate::application::command_handlers::configure::ConfigureCommandHandler;
12-
use crate::domain::environment::{Configuring, Environment};
13-
14-
/// Helper function to create a test environment in Configuring state
15-
pub fn create_test_environment(_temp_dir: &TempDir) -> (Environment<Configuring>, TempDir) {
16-
use crate::domain::environment::testing::EnvironmentTestBuilder;
17-
18-
let (env, _data_dir, _build_dir, env_temp_dir) = EnvironmentTestBuilder::new()
19-
.with_name("test-env")
20-
.build_with_custom_paths();
21-
22-
// Environment is created with paths inside env_temp_dir
23-
// which will be automatically cleaned up when env_temp_dir is dropped
24-
25-
// Transition Created -> Provisioning -> Provisioned -> Configuring
26-
(
27-
env.start_provisioning().provisioned().start_configuring(),
28-
env_temp_dir,
29-
)
30-
}
3112

3213
/// Test builder for `ConfigureCommandHandler` that manages dependencies and lifecycle
3314
///

src/application/command_handlers/configure/tests/integration.rs

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,8 @@
44
55
use std::sync::Arc;
66

7-
use chrono::{TimeZone, Utc};
8-
9-
use super::builders::{create_test_environment, ConfigureCommandHandlerTestBuilder};
7+
use super::builders::ConfigureCommandHandlerTestBuilder;
108
use crate::application::command_handlers::configure::ConfigureCommandHandlerError;
11-
use crate::domain::environment::state::ConfigureStep;
129
use crate::shared::command::CommandError;
1310

1411
#[test]
@@ -30,28 +27,3 @@ fn it_should_have_correct_error_type_conversions() {
3027
let configure_error: ConfigureCommandHandlerError = command_error.into();
3128
drop(configure_error);
3229
}
33-
34-
#[test]
35-
fn it_should_build_failure_context_from_command_error() {
36-
let (command, temp_dir) = ConfigureCommandHandlerTestBuilder::new().build();
37-
38-
// Create test environment for trace generation
39-
let (environment, _env_temp_dir) = create_test_environment(&temp_dir);
40-
41-
let error = ConfigureCommandHandlerError::Command(CommandError::ExecutionFailed {
42-
command: "test".to_string(),
43-
exit_code: "1".to_string(),
44-
stdout: String::new(),
45-
stderr: "test error".to_string(),
46-
});
47-
48-
let started_at = Utc.with_ymd_and_hms(2025, 10, 7, 12, 0, 0).unwrap();
49-
let current_step = ConfigureStep::InstallDocker;
50-
let context = command.build_failure_context(&environment, &error, current_step, started_at);
51-
assert_eq!(context.failed_step, ConfigureStep::InstallDocker);
52-
assert_eq!(
53-
context.error_kind,
54-
crate::shared::ErrorKind::CommandExecution
55-
);
56-
assert_eq!(context.base.execution_started_at, started_at);
57-
}

src/application/command_handlers/destroy/handler.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ impl DestroyCommandHandler {
244244
/// # Returns
245245
///
246246
/// A `DestroyFailureContext` with all failure metadata and trace file path
247-
pub(crate) fn build_failure_context(
247+
fn build_failure_context(
248248
&self,
249249
_environment: &crate::domain::environment::Environment<
250250
crate::domain::environment::Destroying,

src/application/command_handlers/provision/handler.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ impl ProvisionCommandHandler {
332332
/// # Returns
333333
///
334334
/// A `ProvisionFailureContext` with all failure metadata and trace file path
335-
pub(crate) fn build_failure_context(
335+
fn build_failure_context(
336336
&self,
337337
environment: &Environment<Provisioning>,
338338
error: &ProvisionCommandHandlerError,

src/application/command_handlers/provision/tests/builders.rs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,11 @@ use tempfile::TempDir;
1010
use crate::adapters::ansible::AnsibleClient;
1111
use crate::adapters::ssh::SshCredentials;
1212
use crate::application::command_handlers::provision::ProvisionCommandHandler;
13-
use crate::domain::environment::{Environment, Provisioning};
1413
use crate::domain::{InstanceName, ProfileName};
1514
use crate::infrastructure::external_tools::ansible::AnsibleTemplateRenderer;
1615
use crate::infrastructure::external_tools::tofu::TofuTemplateRenderer;
1716
use crate::shared::Username;
1817

19-
pub fn create_test_environment(_temp_dir: &TempDir) -> (Environment<Provisioning>, TempDir) {
20-
use crate::domain::environment::testing::EnvironmentTestBuilder;
21-
22-
let (env, _data_dir, _build_dir, env_temp_dir) = EnvironmentTestBuilder::new()
23-
.with_name("test-env")
24-
.build_with_custom_paths();
25-
26-
// Environment is created with paths inside env_temp_dir
27-
// which will be automatically cleaned up when env_temp_dir is dropped
28-
29-
(env.start_provisioning(), env_temp_dir)
30-
}
31-
3218
/// Test builder for `ProvisionCommandHandler` that manages dependencies and lifecycle
3319
///
3420
/// This builder simplifies test setup by:

src/application/command_handlers/provision/tests/integration.rs

Lines changed: 1 addition & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,10 @@
44
55
use std::sync::Arc;
66

7-
use chrono::{TimeZone, Utc};
8-
9-
use super::builders::{create_test_environment, ProvisionCommandHandlerTestBuilder};
7+
use super::builders::ProvisionCommandHandlerTestBuilder;
108
use crate::adapters::ssh::SshError;
119
use crate::adapters::tofu::client::OpenTofuError;
1210
use crate::application::command_handlers::provision::ProvisionCommandHandlerError;
13-
use crate::domain::environment::state::ProvisionStep;
1411
use crate::infrastructure::external_tools::tofu::ProvisionTemplateError;
1512
use crate::shared::command::CommandError;
1613

@@ -66,113 +63,3 @@ fn it_should_have_correct_error_type_conversions() {
6663
let provision_error: ProvisionCommandHandlerError = ssh_error.into();
6764
drop(provision_error);
6865
}
69-
70-
#[test]
71-
fn it_should_build_failure_context_from_opentofu_template_error() {
72-
let (command_handler, temp_dir, _ssh_credentials) =
73-
ProvisionCommandHandlerTestBuilder::new().build();
74-
75-
let (environment, _env_temp_dir) = create_test_environment(&temp_dir);
76-
77-
let error = ProvisionCommandHandlerError::OpenTofuTemplateRendering(
78-
ProvisionTemplateError::DirectoryCreationFailed {
79-
directory: "/test".to_string(),
80-
source: std::io::Error::new(std::io::ErrorKind::PermissionDenied, "test"),
81-
},
82-
);
83-
84-
let started_at = Utc.with_ymd_and_hms(2025, 10, 7, 12, 0, 0).unwrap();
85-
let current_step = ProvisionStep::RenderOpenTofuTemplates;
86-
let context =
87-
command_handler.build_failure_context(&environment, &error, current_step, started_at);
88-
assert_eq!(context.failed_step, ProvisionStep::RenderOpenTofuTemplates);
89-
assert_eq!(
90-
context.error_kind,
91-
crate::shared::ErrorKind::TemplateRendering
92-
);
93-
assert_eq!(context.base.execution_started_at, started_at);
94-
}
95-
96-
// Note: We don't test AnsibleTemplateRendering errors directly as the error types are complex
97-
// and deeply nested. The build_failure_context method handles them by matching on the
98-
// ProvisionCommandHandlerError::AnsibleTemplateRendering variant, which is sufficient for
99-
// error context generation.
100-
101-
#[test]
102-
fn it_should_build_failure_context_from_ssh_connectivity_error() {
103-
let (command_handler, temp_dir, _ssh_credentials) =
104-
ProvisionCommandHandlerTestBuilder::new().build();
105-
106-
let (environment, _env_temp_dir) = create_test_environment(&temp_dir);
107-
108-
let error = ProvisionCommandHandlerError::SshConnectivity(SshError::ConnectivityTimeout {
109-
host_ip: "127.0.0.1".to_string(),
110-
attempts: 5,
111-
timeout_seconds: 30,
112-
});
113-
114-
let started_at = Utc.with_ymd_and_hms(2025, 10, 7, 12, 0, 0).unwrap();
115-
let current_step = ProvisionStep::WaitSshConnectivity;
116-
let context =
117-
command_handler.build_failure_context(&environment, &error, current_step, started_at);
118-
assert_eq!(context.failed_step, ProvisionStep::WaitSshConnectivity);
119-
assert_eq!(
120-
context.error_kind,
121-
crate::shared::ErrorKind::NetworkConnectivity
122-
);
123-
assert_eq!(context.base.execution_started_at, started_at);
124-
}
125-
126-
#[test]
127-
fn it_should_build_failure_context_from_command_error() {
128-
let (command_handler, temp_dir, _ssh_credentials) =
129-
ProvisionCommandHandlerTestBuilder::new().build();
130-
131-
let (environment, _env_temp_dir) = create_test_environment(&temp_dir);
132-
133-
let error = ProvisionCommandHandlerError::Command(CommandError::ExecutionFailed {
134-
command: "test".to_string(),
135-
exit_code: "1".to_string(),
136-
stdout: String::new(),
137-
stderr: "test error".to_string(),
138-
});
139-
140-
let started_at = Utc.with_ymd_and_hms(2025, 10, 7, 12, 0, 0).unwrap();
141-
let current_step = ProvisionStep::CloudInitWait;
142-
let context =
143-
command_handler.build_failure_context(&environment, &error, current_step, started_at);
144-
assert_eq!(context.failed_step, ProvisionStep::CloudInitWait);
145-
assert_eq!(
146-
context.error_kind,
147-
crate::shared::ErrorKind::CommandExecution
148-
);
149-
assert_eq!(context.base.execution_started_at, started_at);
150-
}
151-
152-
#[test]
153-
fn it_should_build_failure_context_from_opentofu_error() {
154-
let (command_handler, temp_dir, _ssh_credentials) =
155-
ProvisionCommandHandlerTestBuilder::new().build();
156-
157-
let (environment, _env_temp_dir) = create_test_environment(&temp_dir);
158-
159-
let opentofu_error = OpenTofuError::CommandError(CommandError::ExecutionFailed {
160-
command: "tofu init".to_string(),
161-
exit_code: "1".to_string(),
162-
stdout: String::new(),
163-
stderr: "init failed".to_string(),
164-
});
165-
166-
let error = ProvisionCommandHandlerError::OpenTofu(opentofu_error);
167-
168-
let started_at = Utc.with_ymd_and_hms(2025, 10, 7, 12, 0, 0).unwrap();
169-
let current_step = ProvisionStep::OpenTofuInit;
170-
let context =
171-
command_handler.build_failure_context(&environment, &error, current_step, started_at);
172-
assert_eq!(context.failed_step, ProvisionStep::OpenTofuInit);
173-
assert_eq!(
174-
context.error_kind,
175-
crate::shared::ErrorKind::InfrastructureOperation
176-
);
177-
assert_eq!(context.base.execution_started_at, started_at);
178-
}

0 commit comments

Comments
 (0)