-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathintegration.rs
More file actions
282 lines (235 loc) · 9.18 KB
/
Copy pathintegration.rs
File metadata and controls
282 lines (235 loc) · 9.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
//! Integration tests for Create Command
//!
//! These tests verify the complete behavior of `CreateCommandHandler` including
//! interaction with the repository and proper error handling.
use tempfile::TempDir;
use crate::application::command_handlers::create::tests::{
create_valid_test_config, CreateCommandHandlerTestBuilder,
};
use crate::application::command_handlers::create::CreateCommandHandlerError;
use crate::domain::environment::EnvironmentName;
#[test]
fn it_should_create_environment_with_valid_configuration() {
// Arrange
let (command, temp_dir) = CreateCommandHandlerTestBuilder::new().build();
let config = create_valid_test_config(&temp_dir, "test-environment");
// Act
let result = command.execute(config, temp_dir.path());
// Assert
assert!(result.is_ok(), "Expected successful environment creation");
let environment = result.unwrap();
assert_eq!(environment.name().as_str(), "test-environment");
}
#[test]
fn it_should_fail_when_environment_already_exists() {
// Arrange
let (command, temp_dir) = CreateCommandHandlerTestBuilder::new()
.with_existing_environment("test-environment")
.build();
let config = create_valid_test_config(&temp_dir, "test-environment");
// Act
let result = command.execute(config, temp_dir.path());
// Assert
assert!(result.is_err(), "Expected error for duplicate environment");
match result.unwrap_err() {
CreateCommandHandlerError::EnvironmentAlreadyExists { name } => {
assert_eq!(name, "test-environment");
}
other => panic!("Expected EnvironmentAlreadyExists error, got: {other:?}"),
}
}
#[test]
fn it_should_verify_repository_handles_directory_creation() {
// Arrange
let temp_dir = TempDir::new().unwrap();
let (command, builder_temp_dir) = CreateCommandHandlerTestBuilder::new()
.with_base_directory(temp_dir.path())
.build();
let config = create_valid_test_config(&builder_temp_dir, "test-environment");
// Act
let result = command.execute(config, temp_dir.path());
// Assert
assert!(result.is_ok(), "Expected successful environment creation");
let environment = result.unwrap();
// Verify the environment was created with the correct name
assert_eq!(environment.name().as_str(), "test-environment");
// The repository is responsible for directory creation during save.
// We verify this by checking that the environment was persisted successfully,
// which implies the necessary directories were created.
let env_name = EnvironmentName::new("test-environment").unwrap();
let loaded = command
.environment_repository
.load(&env_name)
.expect("Failed to load environment");
assert!(
loaded.is_some(),
"Environment should be persisted in repository"
);
}
#[test]
fn it_should_persist_environment_state_to_repository() {
// Arrange
let (command, temp_dir) = CreateCommandHandlerTestBuilder::new().build();
let config = create_valid_test_config(&temp_dir, "persistent-env");
// Act
let result = command.execute(config, temp_dir.path());
// Assert creation succeeded
assert!(result.is_ok(), "Expected successful environment creation");
let created_environment = result.unwrap();
// Verify environment was persisted by loading it back
let env_name = EnvironmentName::new("persistent-env").unwrap();
let loaded = command
.environment_repository
.load(&env_name)
.expect("Failed to load environment")
.expect("Environment should exist in repository");
// Verify loaded environment matches created one
assert_eq!(loaded.name().as_str(), created_environment.name().as_str());
}
#[test]
fn it_should_fail_with_invalid_environment_name() {
use crate::application::command_handlers::create::config::tracker::TrackerSection;
use crate::application::command_handlers::create::config::{
EnvironmentCreationConfig, EnvironmentSection, LxdProviderSection, ProviderSection,
SshCredentialsConfig,
};
use std::fs;
// Arrange
let (command, temp_dir) = CreateCommandHandlerTestBuilder::new().build();
// Create config with invalid environment name (uppercase not allowed)
let private_key = temp_dir.path().join("id_rsa");
let public_key = temp_dir.path().join("id_rsa.pub");
fs::write(&private_key, "test_private_key").unwrap();
fs::write(&public_key, "test_public_key").unwrap();
let config = EnvironmentCreationConfig::new(
EnvironmentSection {
name: "Invalid_Name".to_string(), // Invalid: contains uppercase
instance_name: None,
},
SshCredentialsConfig::new(
private_key.to_string_lossy().to_string(),
public_key.to_string_lossy().to_string(),
"torrust".to_string(),
22,
),
ProviderSection::Lxd(LxdProviderSection {
profile_name: "test-profile".to_string(),
}),
TrackerSection::default(),
None,
None,
None, // HTTPS configuration
);
// Act
let result = command.execute(config, temp_dir.path());
// Assert
assert!(
result.is_err(),
"Expected error for invalid environment name"
);
match result.unwrap_err() {
CreateCommandHandlerError::InvalidConfiguration(_) => {
// Expected error type
}
other => panic!("Expected InvalidConfiguration error, got: {other:?}"),
}
}
#[test]
fn it_should_fail_when_ssh_private_key_not_found() {
use crate::application::command_handlers::create::config::tracker::TrackerSection;
use crate::application::command_handlers::create::config::{
EnvironmentCreationConfig, EnvironmentSection, LxdProviderSection, ProviderSection,
SshCredentialsConfig,
};
// Arrange
let (command, temp_dir) = CreateCommandHandlerTestBuilder::new().build();
// Create config with non-existent SSH key files
let config = EnvironmentCreationConfig::new(
EnvironmentSection {
name: "test-env".to_string(),
instance_name: None,
},
SshCredentialsConfig::new(
"/nonexistent/private_key".to_string(),
temp_dir
.path()
.join("id_rsa.pub")
.to_string_lossy()
.to_string(),
"torrust".to_string(),
22,
),
ProviderSection::Lxd(LxdProviderSection {
profile_name: "test-profile".to_string(),
}),
TrackerSection::default(),
None,
None,
None, // HTTPS configuration
);
// Act
let result = command.execute(config, temp_dir.path());
// Assert
assert!(
result.is_err(),
"Expected error for non-existent SSH private key"
);
match result.unwrap_err() {
CreateCommandHandlerError::InvalidConfiguration(_) => {
// Expected error type
}
other => panic!("Expected InvalidConfiguration error, got: {other:?}"),
}
}
#[test]
fn it_should_provide_helpful_error_messages() {
// Arrange
let (command, temp_dir) = CreateCommandHandlerTestBuilder::new()
.with_existing_environment("existing-env")
.build();
let config = create_valid_test_config(&temp_dir, "existing-env");
// Act
let result = command.execute(config, temp_dir.path());
// Assert
assert!(result.is_err());
let error = result.unwrap_err();
// Verify error has help method
let help = error.help();
assert!(!help.is_empty(), "Help text should not be empty");
assert!(
help.contains("already exists") || help.contains("Troubleshooting"),
"Help should contain actionable guidance"
);
}
#[test]
fn it_should_create_multiple_different_environments() {
// Arrange
let (command, temp_dir) = CreateCommandHandlerTestBuilder::new().build();
// Act: Create first environment
let config1 = create_valid_test_config(&temp_dir, "environment-1");
let result1 = command.execute(config1, temp_dir.path());
assert!(result1.is_ok(), "First environment should be created");
// Act: Create second environment
let config2 = create_valid_test_config(&temp_dir, "environment-2");
let result2 = command.execute(config2, temp_dir.path());
assert!(result2.is_ok(), "Second environment should be created");
// Assert: Both environments exist
let env1_name = EnvironmentName::new("environment-1").unwrap();
let env2_name = EnvironmentName::new("environment-2").unwrap();
assert!(command.environment_repository.exists(&env1_name).unwrap());
assert!(command.environment_repository.exists(&env2_name).unwrap());
}
#[test]
fn it_should_use_deterministic_timestamps_with_mock_clock() {
use chrono::TimeZone;
// Arrange
let fixed_time = chrono::Utc.with_ymd_and_hms(2025, 1, 1, 12, 0, 0).unwrap();
let (command, temp_dir) = CreateCommandHandlerTestBuilder::new()
.with_fixed_time(fixed_time)
.build();
let config = create_valid_test_config(&temp_dir, "test-env");
// Act
let _result = command.execute(config, temp_dir.path());
// Assert: Clock maintains fixed time
assert_eq!(command.clock.now(), fixed_time);
}