use anyhow::Result;
use ralph::contracts::TaskStatus;
mod test_support;
#[test]
fn queue_import_malformed_json_no_snapshot() -> Result<()> {
let dir = test_support::temp_dir_outside_repo();
test_support::git_init(dir.path())?;
test_support::seed_ralph_dir(dir.path())?;
let task = test_support::make_test_task("RQ-0001", "Test task", TaskStatus::Todo);
test_support::write_queue(dir.path(), &[task])?;
test_support::write_done(dir.path(), &[])?;
let bad_json_path = dir.path().join("bad_import.json");
std::fs::write(&bad_json_path, b"{ this is not valid json }")?;
let (status, _stdout, _stderr) = test_support::run_in_dir(
dir.path(),
&[
"queue",
"import",
"--format",
"json",
"--input",
bad_json_path.to_str().unwrap(),
],
);
anyhow::ensure!(!status.success(), "import should fail with malformed JSON");
let (status, stdout, stderr) = test_support::run_in_dir(dir.path(), &["undo", "--list"]);
anyhow::ensure!(status.success(), "undo --list failed\nstderr:\n{stderr}");
anyhow::ensure!(
stdout.contains("No continuation checkpoints are available"),
"expected no snapshots after failed import, got:\n{stdout}"
);
Ok(())
}
#[test]
fn queue_import_valid_json_creates_snapshot() -> Result<()> {
let dir = test_support::temp_dir_outside_repo();
test_support::git_init(dir.path())?;
test_support::seed_ralph_dir(dir.path())?;
let task = test_support::make_test_task("RQ-0001", "Test task", TaskStatus::Todo);
test_support::write_queue(dir.path(), &[task])?;
test_support::write_done(dir.path(), &[])?;
let good_json_path = dir.path().join("good_import.json");
let import_data = r#"[{"id": "RQ-0002", "title": "Imported task", "status": "todo"}]"#;
std::fs::write(&good_json_path, import_data)?;
let (status, _stdout, _stderr) = test_support::run_in_dir(
dir.path(),
&[
"queue",
"import",
"--format",
"json",
"--input",
good_json_path.to_str().unwrap(),
],
);
anyhow::ensure!(
status.success(),
"import should succeed\nstderr:\n{_stderr}"
);
let (status, stdout, stderr) = test_support::run_in_dir(dir.path(), &["undo", "--list"]);
anyhow::ensure!(status.success(), "undo --list failed\nstderr:\n{stderr}");
anyhow::ensure!(
stdout.contains("Available continuation checkpoints"),
"expected snapshot after successful import, got:\n{stdout}"
);
anyhow::ensure!(
stdout.contains("queue import"),
"expected 'queue import' operation in snapshot list, got:\n{stdout}"
);
Ok(())
}
#[test]
fn queue_import_malformed_csv_no_snapshot() -> Result<()> {
let dir = test_support::temp_dir_outside_repo();
test_support::git_init(dir.path())?;
test_support::seed_ralph_dir(dir.path())?;
let task = test_support::make_test_task("RQ-0001", "Test task", TaskStatus::Todo);
test_support::write_queue(dir.path(), &[task])?;
test_support::write_done(dir.path(), &[])?;
let bad_csv_path = dir.path().join("bad_import.csv");
std::fs::write(&bad_csv_path, b"id,status\nRQ-0002,todo")?;
let (status, _stdout, _stderr) = test_support::run_in_dir(
dir.path(),
&[
"queue",
"import",
"--format",
"csv",
"--input",
bad_csv_path.to_str().unwrap(),
],
);
anyhow::ensure!(
!status.success(),
"import should fail with missing title column"
);
let (status, stdout, stderr) = test_support::run_in_dir(dir.path(), &["undo", "--list"]);
anyhow::ensure!(status.success(), "undo --list failed\nstderr:\n{stderr}");
anyhow::ensure!(
stdout.contains("No continuation checkpoints are available"),
"expected no snapshots after failed import, got:\n{stdout}"
);
Ok(())
}
#[test]
fn queue_import_dry_run_no_snapshot() -> Result<()> {
let dir = test_support::temp_dir_outside_repo();
test_support::git_init(dir.path())?;
test_support::seed_ralph_dir(dir.path())?;
let task = test_support::make_test_task("RQ-0001", "Test task", TaskStatus::Todo);
test_support::write_queue(dir.path(), &[task])?;
test_support::write_done(dir.path(), &[])?;
let json_path = dir.path().join("import.json");
let import_data = r#"[{"id": "RQ-0002", "title": "Imported task", "status": "todo"}]"#;
std::fs::write(&json_path, import_data)?;
let (status, _stdout, _stderr) = test_support::run_in_dir(
dir.path(),
&[
"queue",
"import",
"--format",
"json",
"--input",
json_path.to_str().unwrap(),
"--dry-run",
],
);
anyhow::ensure!(
status.success(),
"import --dry-run should succeed\nstderr:\n{_stderr}"
);
let (status, stdout, stderr) = test_support::run_in_dir(dir.path(), &["undo", "--list"]);
anyhow::ensure!(status.success(), "undo --list failed\nstderr:\n{stderr}");
anyhow::ensure!(
stdout.contains("No continuation checkpoints are available"),
"expected no snapshots after dry-run import, got:\n{stdout}"
);
Ok(())
}
#[test]
fn queue_import_duplicate_fail_no_snapshot() -> Result<()> {
let dir = test_support::temp_dir_outside_repo();
test_support::git_init(dir.path())?;
test_support::seed_ralph_dir(dir.path())?;
let task = test_support::make_test_task("RQ-0001", "Test task", TaskStatus::Todo);
test_support::write_queue(dir.path(), &[task])?;
test_support::write_done(dir.path(), &[])?;
let dup_json_path = dir.path().join("dup_import.json");
let import_data = r#"[{"id": "RQ-0001", "title": "Duplicate task", "status": "todo"}]"#;
std::fs::write(&dup_json_path, import_data)?;
let (status, _stdout, _stderr) = test_support::run_in_dir(
dir.path(),
&[
"queue",
"import",
"--format",
"json",
"--input",
dup_json_path.to_str().unwrap(),
],
);
anyhow::ensure!(!status.success(), "import should fail with duplicate ID");
let (status, stdout, stderr) = test_support::run_in_dir(dir.path(), &["undo", "--list"]);
anyhow::ensure!(status.success(), "undo --list failed\nstderr:\n{stderr}");
anyhow::ensure!(
stdout.contains("No continuation checkpoints are available"),
"expected no snapshots after failed duplicate import, got:\n{stdout}"
);
Ok(())
}
#[test]
fn queue_import_missing_file_no_snapshot() -> Result<()> {
let dir = test_support::temp_dir_outside_repo();
test_support::git_init(dir.path())?;
test_support::seed_ralph_dir(dir.path())?;
let task = test_support::make_test_task("RQ-0001", "Test task", TaskStatus::Todo);
test_support::write_queue(dir.path(), &[task])?;
test_support::write_done(dir.path(), &[])?;
let missing_path = dir.path().join("nonexistent.json");
let (status, _stdout, _stderr) = test_support::run_in_dir(
dir.path(),
&[
"queue",
"import",
"--format",
"json",
"--input",
missing_path.to_str().unwrap(),
],
);
anyhow::ensure!(!status.success(), "import should fail with missing file");
let (status, stdout, stderr) = test_support::run_in_dir(dir.path(), &["undo", "--list"]);
anyhow::ensure!(status.success(), "undo --list failed\nstderr:\n{stderr}");
anyhow::ensure!(
stdout.contains("No continuation checkpoints are available"),
"expected no snapshots after failed import with missing file, got:\n{stdout}"
);
Ok(())
}