use assert_cmd::cargo::cargo_bin;
use predicates::prelude::*;
use sylphx_wire_mock::WireMockServer;
use tokio::process::Command;
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn cli_all_shipped_commands_twice() {
let mock = WireMockServer::start().await;
let base = mock.management_base_url();
let bin = cargo_bin!("sylphx");
let runs: &[&[&str]] = &[
&["health", "--json"],
&["whoami", "--json"],
&["orgs", "list", "--json"],
&["projects", "list", "--json"],
&["projects", "get", "prj_demo", "--json"],
&["environments", "list", "prj_demo", "--json"],
&["environments", "get", "prj_demo", "env_prod", "--json"],
&["deployments", "list", "prj_demo", "--json"],
&["api", "get", "/projects", "--json"],
&["version-info", "--json"],
];
for run in 1..=2 {
for args in runs {
let mut cmd = Command::new(&bin);
if *args != &["version-info", "--json"] {
cmd.args(["--token", "svc_test", "--api-url", &base]);
}
let output = cmd.args(*args).output().await.expect("spawn");
assert!(
output.status.success(),
"run {run} {:?} failed: {}",
args,
String::from_utf8_lossy(&output.stderr)
);
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(!stdout.trim().is_empty(), "run {run} {:?} empty stdout", args);
match args[0] {
"health" => assert!(stdout.contains("ok"), "run {run}: {stdout}"),
"whoami" => assert!(stdout.contains("user_1"), "run {run}: {stdout}"),
"orgs" => assert!(stdout.contains("acme"), "run {run}: {stdout}"),
"projects" if args.get(1) == Some(&"list") => {
assert!(stdout.contains("prj_demo"), "run {run}: {stdout}")
}
"projects" if args.get(1) == Some(&"get") => {
assert!(stdout.contains("Demo"), "run {run}: {stdout}")
}
"environments" if args.get(1) == Some(&"list") => {
assert!(stdout.contains("production"), "run {run}: {stdout}")
}
"environments" if args.get(1) == Some(&"get") => {
assert!(stdout.contains("env_prod") || stdout.contains("production"), "run {run}: {stdout}")
}
"deployments" => {
assert!(stdout.contains("dep_1"), "run {run}: {stdout}");
assert!(stdout.contains("ready"), "run {run}: {stdout}");
}
"api" => {
assert!(stdout.contains("\"status\""), "run {run}: {stdout}");
assert!(stdout.contains("demo"), "run {run}: {stdout}");
}
"version-info" => {
assert!(stdout.contains("sylphx-sdk-management"), "run {run}: {stdout}");
assert!(stdout.contains("shippedCommands"), "run {run}: {stdout}");
assert!(stdout.contains("environments list"), "run {run}: {stdout}");
assert!(stdout.contains("deployments list"), "run {run}: {stdout}");
assert!(stdout.contains("\"product\": \"rust\"") || stdout.contains("\"product\":\"rust\""), "run {run}: {stdout}");
}
_ => {}
}
}
}
mock.shutdown().await;
}
#[test]
fn cli_rejects_missing_token() {
let bin = cargo_bin!("sylphx");
let assert = assert_cmd::Command::new(bin)
.env_remove("SYLPHX_TOKEN")
.args(["health"])
.assert();
assert
.failure()
.stderr(predicate::str::contains("SYLPHX_TOKEN").or(predicate::str::contains("token")));
}
#[test]
fn cli_help_lists_day1_commands() {
let bin = cargo_bin!("sylphx");
let assert = assert_cmd::Command::new(bin).arg("--help").assert();
assert
.success()
.stdout(predicate::str::contains("environments"))
.stdout(predicate::str::contains("deployments"))
.stdout(predicate::str::contains("health"))
.stdout(predicate::str::contains("api"));
}