Skip to content

Commit 3f2e9fd

Browse files
committed
tests: improve coverage
1 parent 28b20d3 commit 3f2e9fd

8 files changed

Lines changed: 1094 additions & 0 deletions

File tree

plugins/repos-health/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,6 @@ chrono = { version = "0.4", features = ["serde"] }
1515

1616
[dependencies.repos]
1717
path = "../.."
18+
19+
[dev-dependencies]
20+
tempfile = "3"

plugins/repos-health/src/main.rs

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,3 +188,109 @@ fn short_timestamp() -> String {
188188
let now = Utc::now();
189189
format!("{}", now.format("%Y%m%d"))
190190
}
191+
192+
#[cfg(test)]
193+
mod tests {
194+
use super::*;
195+
use tempfile::TempDir;
196+
197+
#[test]
198+
fn test_print_help() {
199+
// Test that print_help function executes without panicking
200+
print_help();
201+
// If we reach this point, the function executed successfully
202+
// Test passes if print_help() completes without panicking
203+
}
204+
205+
#[test]
206+
fn test_short_timestamp_format() {
207+
let timestamp = short_timestamp();
208+
// Should be 8 characters in YYYYMMDD format
209+
assert_eq!(timestamp.len(), 8);
210+
// Should be all digits
211+
assert!(timestamp.chars().all(|c| c.is_ascii_digit()));
212+
}
213+
214+
#[test]
215+
fn test_check_outdated_execution() {
216+
// Test execution path for check_outdated function
217+
let temp_dir = TempDir::new().unwrap();
218+
let repo_path = temp_dir.path();
219+
220+
// This will hit the npm command execution path
221+
// Expected to return empty vec since npm likely not available in test environment
222+
let result = check_outdated(repo_path);
223+
assert!(result.is_ok());
224+
}
225+
226+
#[test]
227+
fn test_update_dependencies_execution() {
228+
// Test execution path for update_dependencies function
229+
let temp_dir = TempDir::new().unwrap();
230+
let repo_path = temp_dir.path();
231+
232+
// This will execute the npm update command path
233+
let result = update_dependencies(repo_path);
234+
assert!(result.is_ok()); // Should always succeed (ignores npm failures)
235+
}
236+
237+
#[test]
238+
fn test_has_lockfile_changes_execution() {
239+
// Test execution path for has_lockfile_changes function
240+
let temp_dir = TempDir::new().unwrap();
241+
let repo_path = temp_dir.path();
242+
243+
// Initialize a git repo for the test
244+
let _ = Command::new("git")
245+
.arg("init")
246+
.current_dir(repo_path)
247+
.output();
248+
249+
// This will hit the git status execution path
250+
let result = has_lockfile_changes(repo_path);
251+
// May succeed or fail depending on git setup, but tests execution path
252+
let _ = result; // Don't assert result since git may not be available
253+
}
254+
255+
#[test]
256+
fn test_process_repo_no_package_json() {
257+
// Test process_repo execution path when no package.json exists
258+
let temp_dir = TempDir::new().unwrap();
259+
260+
let repo = Repository {
261+
name: "test-repo".to_string(),
262+
url: "https://github.com/test/repo.git".to_string(),
263+
path: Some(temp_dir.path().to_string_lossy().to_string()),
264+
branch: None,
265+
tags: vec![],
266+
config_dir: None,
267+
};
268+
269+
// This should hit the "no package.json" error path
270+
let result = process_repo(&repo);
271+
assert!(result.is_err());
272+
assert!(result.unwrap_err().to_string().contains("no package.json"));
273+
}
274+
275+
#[test]
276+
fn test_run_command_execution() {
277+
// Test the run function execution path
278+
let temp_dir = TempDir::new().unwrap();
279+
let repo_path = temp_dir.path();
280+
281+
// Test with a simple command that should succeed
282+
let result = run(repo_path, ["echo", "test"]);
283+
assert!(result.is_ok());
284+
}
285+
286+
#[test]
287+
fn test_run_command_failure() {
288+
// Test the run function error path
289+
let temp_dir = TempDir::new().unwrap();
290+
let repo_path = temp_dir.path();
291+
292+
// Test with a command that should fail
293+
let result = run(repo_path, ["nonexistent_command_12345"]);
294+
assert!(result.is_err());
295+
}
296+
}

src/commands/pr.rs

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,176 @@ impl Command for PrCommand {
142142
Ok(())
143143
}
144144
}
145+
146+
#[cfg(test)]
147+
mod tests {
148+
use super::*;
149+
use crate::config::{Config, Repository};
150+
151+
#[tokio::test]
152+
async fn test_pr_command_no_repositories() {
153+
let config = Config {
154+
repositories: vec![],
155+
recipes: vec![],
156+
};
157+
let context = CommandContext {
158+
config,
159+
tag: vec![],
160+
exclude_tag: vec![],
161+
repos: None,
162+
parallel: false,
163+
};
164+
165+
let pr_command = PrCommand {
166+
title: "Test PR".to_string(),
167+
body: "Test body".to_string(),
168+
branch_name: None,
169+
base_branch: None,
170+
commit_msg: None,
171+
draft: false,
172+
token: "test_token".to_string(),
173+
create_only: false,
174+
};
175+
176+
let result = pr_command.execute(&context).await;
177+
assert!(result.is_ok());
178+
}
179+
180+
#[tokio::test]
181+
async fn test_pr_command_with_filters() {
182+
let repository = Repository {
183+
name: "test-repo".to_string(),
184+
url: "https://github.com/test/repo.git".to_string(),
185+
path: Some("./test-repo".to_string()),
186+
branch: None,
187+
tags: vec!["api".to_string()],
188+
config_dir: None,
189+
};
190+
191+
let config = Config {
192+
repositories: vec![repository],
193+
recipes: vec![],
194+
};
195+
196+
let context = CommandContext {
197+
config,
198+
tag: vec!["nonexistent".to_string()],
199+
exclude_tag: vec![],
200+
repos: None,
201+
parallel: false,
202+
};
203+
204+
let pr_command = PrCommand {
205+
title: "Test PR".to_string(),
206+
body: "Test body".to_string(),
207+
branch_name: Some("feature/test".to_string()),
208+
base_branch: Some("main".to_string()),
209+
commit_msg: Some("Test commit".to_string()),
210+
draft: true,
211+
token: "test_token".to_string(),
212+
create_only: true,
213+
};
214+
215+
let result = pr_command.execute(&context).await;
216+
assert!(result.is_ok());
217+
}
218+
219+
#[tokio::test]
220+
async fn test_pr_command_execution_paths() {
221+
let repository = Repository {
222+
name: "test-repo".to_string(),
223+
url: "https://github.com/test/repo.git".to_string(),
224+
path: Some("./nonexistent-path".to_string()),
225+
branch: None,
226+
tags: vec!["backend".to_string()],
227+
config_dir: None,
228+
};
229+
230+
let config = Config {
231+
repositories: vec![repository],
232+
recipes: vec![],
233+
};
234+
235+
let context = CommandContext {
236+
config,
237+
tag: vec!["backend".to_string()],
238+
exclude_tag: vec![],
239+
repos: None,
240+
parallel: false,
241+
};
242+
243+
let pr_command = PrCommand {
244+
title: "Integration Test PR".to_string(),
245+
body: "Integration test body".to_string(),
246+
branch_name: None,
247+
base_branch: None,
248+
commit_msg: None,
249+
draft: false,
250+
token: "test_token".to_string(),
251+
create_only: false,
252+
};
253+
254+
// This will hit the error handling paths since the repo doesn't exist
255+
let result = pr_command.execute(&context).await;
256+
assert!(result.is_err()); // Expect error due to nonexistent repository
257+
}
258+
259+
#[tokio::test]
260+
async fn test_pr_command_parallel_execution() {
261+
let repository = Repository {
262+
name: "test-repo-parallel".to_string(),
263+
url: "https://github.com/test/repo.git".to_string(),
264+
path: Some("./nonexistent-parallel".to_string()),
265+
branch: None,
266+
tags: vec!["test".to_string()],
267+
config_dir: None,
268+
};
269+
270+
let config = Config {
271+
repositories: vec![repository],
272+
recipes: vec![],
273+
};
274+
275+
let context = CommandContext {
276+
config,
277+
tag: vec!["test".to_string()],
278+
exclude_tag: vec![],
279+
repos: None,
280+
parallel: true, // Test parallel execution path
281+
};
282+
283+
let pr_command = PrCommand {
284+
title: "Parallel Test PR".to_string(),
285+
body: "Parallel test body".to_string(),
286+
branch_name: None,
287+
base_branch: None,
288+
commit_msg: None,
289+
draft: false,
290+
token: "test_token".to_string(),
291+
create_only: false,
292+
};
293+
294+
// This will hit the parallel execution error handling paths
295+
let result = pr_command.execute(&context).await;
296+
assert!(result.is_err()); // Expect error due to nonexistent repository
297+
}
298+
299+
#[tokio::test]
300+
async fn test_pr_command_module_exists() {
301+
// Test to ensure the PR command module is properly accessible
302+
let pr_command = PrCommand {
303+
title: "Module Test".to_string(),
304+
body: "Module test body".to_string(),
305+
branch_name: None,
306+
base_branch: None,
307+
commit_msg: None,
308+
draft: false,
309+
token: "test_token".to_string(),
310+
create_only: false,
311+
};
312+
313+
assert_eq!(pr_command.title, "Module Test");
314+
assert!(!pr_command.draft);
315+
assert!(!pr_command.create_only);
316+
}
317+
}

0 commit comments

Comments
 (0)