mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-09-23 00:41:13 +00:00
Keep local server targeting based on explicit server targets instead of implicitly deriving a socket from storage_dir. This makes ~/.fabro/fabro.sock the default local socket again, keeps storage under ~/.fabro/storage, threads FABRO_CONFIG through server autostart paths, and updates the CLI test harness for the new split.
82 lines
3 KiB
Rust
82 lines
3 KiB
Rust
use fabro_test::{fabro_snapshot, test_context};
|
|
use serde_json::Value;
|
|
|
|
use super::support::fixture;
|
|
|
|
#[test]
|
|
fn help() {
|
|
let context = test_context!();
|
|
let mut cmd = context.command();
|
|
cmd.args(["preflight", "--help"]);
|
|
fabro_snapshot!(context.filters(), cmd, @"
|
|
success: true
|
|
exit_code: 0
|
|
----- stdout -----
|
|
Validate run configuration without executing
|
|
|
|
Usage: fabro preflight [OPTIONS] <WORKFLOW>
|
|
|
|
Arguments:
|
|
<WORKFLOW> Path to a .fabro workflow file or .toml task config
|
|
|
|
Options:
|
|
--json Output as JSON [env: FABRO_JSON=]
|
|
--server <SERVER> Fabro server target: http(s) URL or absolute Unix socket path [env: FABRO_SERVER=]
|
|
--debug Enable DEBUG-level logging (default is INFO) [env: FABRO_DEBUG=]
|
|
--goal <GOAL> Override the workflow goal (exposed as $goal in prompts)
|
|
--goal-file <GOAL_FILE> Read the workflow goal from a file
|
|
--no-upgrade-check Disable automatic upgrade check [env: FABRO_NO_UPGRADE_CHECK=true]
|
|
--model <MODEL> Override default LLM model
|
|
--quiet Suppress non-essential output [env: FABRO_QUIET=]
|
|
--provider <PROVIDER> Override default LLM provider
|
|
-v, --verbose Enable verbose output
|
|
--sandbox <SANDBOX> Sandbox for agent tools [possible values: local, docker, daytona]
|
|
-h, --help Print help
|
|
----- stderr -----
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn preflight_invalid_workflow_fails_with_validation_output() {
|
|
let context = test_context!();
|
|
let workflow = fixture("invalid.fabro");
|
|
let mut cmd = context.command();
|
|
cmd.args(["preflight", workflow.to_str().unwrap()]);
|
|
|
|
fabro_snapshot!(context.filters(), cmd, @"
|
|
success: false
|
|
exit_code: 1
|
|
----- stdout -----
|
|
----- stderr -----
|
|
Workflow: Invalid (2 nodes, 1 edges)
|
|
Graph: [FIXTURES]/invalid.fabro
|
|
error: Pipeline must have exactly one start node (shape=Mdiamond or id start/Start) (start_node)
|
|
error [node: exit]: Exit node 'exit' has 1 outgoing edge(s) but must have none (exit_no_outgoing)
|
|
error: Validation failed
|
|
");
|
|
}
|
|
|
|
#[test]
|
|
fn preflight_invalid_workflow_json_emits_diagnostics() {
|
|
let context = test_context!();
|
|
let workflow = fixture("invalid.fabro");
|
|
let output = context
|
|
.command()
|
|
.args(["--json", "preflight", workflow.to_str().unwrap()])
|
|
.output()
|
|
.expect("command should run");
|
|
|
|
assert!(!output.status.success());
|
|
let value: Value =
|
|
serde_json::from_slice(&output.stdout).expect("preflight --json should parse");
|
|
assert_eq!(value["workflow"]["name"], "Invalid");
|
|
assert!(
|
|
value["workflow"]["diagnostics"]
|
|
.as_array()
|
|
.is_some_and(|diagnostics| !diagnostics.is_empty())
|
|
);
|
|
assert_eq!(value["checks"]["title"], "Run Preflight");
|
|
|
|
let stderr = String::from_utf8(output.stderr).unwrap();
|
|
assert!(stderr.contains("Validation failed"));
|
|
}
|