131 lines
4.2 KiB
Rust
131 lines
4.2 KiB
Rust
use std::process::Command;
|
|
use tempfile::TempDir;
|
|
|
|
fn run_ldr(dir: &TempDir, args: &[&str]) -> std::process::Output {
|
|
Command::new(env!("CARGO_BIN_EXE_ldr"))
|
|
.env("XDG_DATA_HOME", dir.path())
|
|
.args(args)
|
|
.output()
|
|
.expect("Failed to run ldr")
|
|
}
|
|
|
|
#[test]
|
|
fn test_empty_task_rejected() {
|
|
let dir = TempDir::new().unwrap();
|
|
|
|
// Try to add empty task
|
|
let output = run_ldr(&dir, &["add", ""]);
|
|
assert!(!output.status.success());
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
assert!(stderr.contains("Cannot add empty task"));
|
|
|
|
// Try to add whitespace-only task
|
|
let output = run_ldr(&dir, &["add", " "]);
|
|
assert!(!output.status.success());
|
|
}
|
|
|
|
#[test]
|
|
fn test_task_length_limit() {
|
|
let dir = TempDir::new().unwrap();
|
|
|
|
// Create a very long task (over 500 chars)
|
|
let long_text = "x".repeat(501);
|
|
let output = run_ldr(&dir, &["add", &long_text]);
|
|
assert!(!output.status.success());
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
assert!(stderr.contains("Task text too long"));
|
|
assert!(stderr.contains("Maximum length is 500"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_max_subtasks_limit() {
|
|
let dir = TempDir::new().unwrap();
|
|
|
|
// Add a main task
|
|
run_ldr(&dir, &["add", "Main task"]);
|
|
|
|
// Add 26 subtasks (a-z)
|
|
for i in 0..26 {
|
|
let subtask = format!("Subtask {}", i);
|
|
let output = run_ldr(&dir, &["add", &subtask, "--under", "1"]);
|
|
assert!(output.status.success());
|
|
}
|
|
|
|
// Try to add 27th subtask - should fail
|
|
let output = run_ldr(&dir, &["add", "One too many", "--under", "1"]);
|
|
assert!(!output.status.success());
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
assert!(stderr.contains("already has maximum number of subtasks"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_invalid_task_references() {
|
|
let dir = TempDir::new().unwrap();
|
|
|
|
// Add some tasks
|
|
run_ldr(&dir, &["add", "Task 1"]);
|
|
run_ldr(&dir, &["add", "Task 2"]);
|
|
|
|
// Test zero task number - should print error but return success
|
|
let output = run_ldr(&dir, &["up", "0"]);
|
|
// Check that error message was printed even if exit code is 0
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
assert!(
|
|
stdout.contains("Invalid task reference")
|
|
|| stdout.contains("Task number must be at least 1")
|
|
);
|
|
|
|
// Test too large task number
|
|
let output = run_ldr(&dir, &["up", "999"]);
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
assert!(stdout.contains("Invalid task number"));
|
|
|
|
// Test invalid formats
|
|
let output = run_ldr(&dir, &["up", "1A"]); // uppercase letter
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
assert!(stdout.contains("Invalid") || stdout.contains("uppercase"));
|
|
|
|
let output = run_ldr(&dir, &["up", "abc"]); // no number
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
assert!(stdout.contains("Invalid") || stdout.contains("must start with a number"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_subtask_under_invalid_parent() {
|
|
let dir = TempDir::new().unwrap();
|
|
|
|
// Try to add subtask under non-existent task
|
|
let output = run_ldr(&dir, &["add", "Subtask", "--under", "1"]);
|
|
assert!(!output.status.success());
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
assert!(stderr.contains("Invalid task number"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_deep_nesting_prevention() {
|
|
let dir = TempDir::new().unwrap();
|
|
|
|
// Create a markdown file with deep nesting
|
|
// ldr stores files in a subdirectory
|
|
std::fs::create_dir_all(dir.path().join("ldr")).unwrap();
|
|
let todos_path = dir.path().join("ldr").join("todos.md");
|
|
let content = r#"# TODOs
|
|
|
|
- Task 1
|
|
- Subtask 1
|
|
- Deep subtask (should be flattened)
|
|
- Very deep subtask (should be flattened)
|
|
"#;
|
|
std::fs::write(&todos_path, content).unwrap();
|
|
|
|
// List tasks - deep nesting should be handled silently now
|
|
// (warnings are printed during parse but list should work)
|
|
let output = run_ldr(&dir, &["ls", "-a"]);
|
|
assert!(output.status.success());
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
|
|
// The deep subtasks should appear as regular subtasks (flattened)
|
|
// We should see the subtasks in the output
|
|
assert!(stdout.contains("Subtask 1") || stdout.contains("a."));
|
|
}
|