mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-09-11 22:53:00 +00:00
test(cli): add end-to-end archive lifecycle scenario
Single #[test] that exercises the full CLI archive flow: run a dry-run to succeeded, verify ps -a shows it, archive, verify default ps hides it and ps -a shows archived, unarchive, verify the prior terminal status is restored, then re-archive and rm to confirm archived runs remain delete-able (plan Scope Boundaries).
This commit is contained in:
parent
13a501ec1d
commit
05743050ec
2 changed files with 102 additions and 0 deletions
101
lib/crates/fabro-cli/tests/it/scenario/archive.rs
Normal file
101
lib/crates/fabro-cli/tests/it/scenario/archive.rs
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
//! End-to-end CLI lifecycle for the archived run status: run → archive →
|
||||
//! hide/show → unarchive → still-deletable.
|
||||
|
||||
use fabro_test::test_context;
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::cmd::support::setup_completed_fast_dry_run;
|
||||
|
||||
fn ps_runs(context: &fabro_test::TestContext, include_archived: bool) -> Vec<Value> {
|
||||
let mut cmd = context.ps();
|
||||
let mut args = vec!["--json", "--label", ""];
|
||||
// `--label` needs the actual label value; we replace the empty slot below.
|
||||
let label = context.test_case_label();
|
||||
args[2] = &label;
|
||||
if include_archived {
|
||||
cmd.args(["-a"]);
|
||||
}
|
||||
cmd.args(args);
|
||||
let output = cmd.output().expect("ps should execute");
|
||||
assert!(
|
||||
output.status.success(),
|
||||
"ps failed\nstdout:\n{}\nstderr:\n{}",
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
);
|
||||
serde_json::from_slice(&output.stdout).expect("ps JSON should parse")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn archive_lifecycle_end_to_end() {
|
||||
let context = test_context!();
|
||||
let run = setup_completed_fast_dry_run(&context);
|
||||
|
||||
// 1. Baseline: `ps -a` sees the succeeded run.
|
||||
let visible = ps_runs(&context, true);
|
||||
assert_eq!(visible.len(), 1);
|
||||
assert_eq!(visible[0]["run_id"], run.run_id);
|
||||
assert_eq!(visible[0]["status"], "succeeded");
|
||||
|
||||
// 2. Archive the run.
|
||||
let archive = context
|
||||
.command()
|
||||
.args(["archive", &run.run_id])
|
||||
.output()
|
||||
.expect("archive should execute");
|
||||
assert!(
|
||||
archive.status.success(),
|
||||
"archive failed\nstderr:\n{}",
|
||||
String::from_utf8_lossy(&archive.stderr)
|
||||
);
|
||||
|
||||
// 3. Default `ps` hides archived runs.
|
||||
let default_visible = ps_runs(&context, false);
|
||||
assert!(
|
||||
default_visible.is_empty(),
|
||||
"default ps should hide archived, got {default_visible:?}"
|
||||
);
|
||||
|
||||
// 4. `ps -a` surfaces the run with status `archived`.
|
||||
let with_archived = ps_runs(&context, true);
|
||||
assert_eq!(with_archived.len(), 1);
|
||||
assert_eq!(with_archived[0]["run_id"], run.run_id);
|
||||
assert_eq!(with_archived[0]["status"], "archived");
|
||||
|
||||
// 5. Unarchive restores the prior terminal status.
|
||||
let unarchive = context
|
||||
.command()
|
||||
.args(["unarchive", &run.run_id])
|
||||
.output()
|
||||
.expect("unarchive should execute");
|
||||
assert!(
|
||||
unarchive.status.success(),
|
||||
"unarchive failed\nstderr:\n{}",
|
||||
String::from_utf8_lossy(&unarchive.stderr)
|
||||
);
|
||||
let restored = ps_runs(&context, true);
|
||||
assert_eq!(restored[0]["status"], "succeeded");
|
||||
|
||||
// 6. Archived runs remain delete-able (plan Scope Boundaries).
|
||||
context
|
||||
.command()
|
||||
.args(["archive", &run.run_id])
|
||||
.output()
|
||||
.expect("re-archive should execute");
|
||||
let rm = context
|
||||
.command()
|
||||
.args(["rm", &run.run_id])
|
||||
.output()
|
||||
.expect("rm should execute");
|
||||
assert!(
|
||||
rm.status.success(),
|
||||
"rm on archived run should succeed\nstderr:\n{}",
|
||||
String::from_utf8_lossy(&rm.stderr)
|
||||
);
|
||||
assert!(!run.run_dir.exists(), "run directory should be deleted");
|
||||
let after_delete = ps_runs(&context, true);
|
||||
assert!(
|
||||
after_delete.is_empty(),
|
||||
"run should be gone after rm, got {after_delete:?}"
|
||||
);
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
#![allow(clippy::absolute_paths)]
|
||||
|
||||
mod archive;
|
||||
mod artifacts;
|
||||
mod exec;
|
||||
mod lifecycle;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue