use assert_cmd::Command;
use predicates::prelude::*;
use std::path::PathBuf;
use tempfile::TempDir;
fn workspace_fixture_config() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/workspace/svccat.toml")
}
fn manifest_basic_fixture() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/rules/manifest-basic.yaml")
}
#[test]
fn workspace_check_format_html_renders_real_html_via_binary() {
Command::cargo_bin("svccat")
.unwrap()
.arg("workspace")
.arg("check")
.arg("--config")
.arg(workspace_fixture_config())
.arg("--format")
.arg("html")
.assert()
.success()
.stdout(predicate::str::contains("<!DOCTYPE html>"))
.stdout(predicate::str::contains("backend"))
.stdout(predicate::str::contains("frontend"));
}
#[test]
fn workspace_check_format_json_emits_real_json_via_binary() {
Command::cargo_bin("svccat")
.unwrap()
.arg("workspace")
.arg("check")
.arg("--config")
.arg(workspace_fixture_config())
.arg("--format")
.arg("json")
.assert()
.success()
.stdout(predicate::str::contains("\"total_declared\": 4"))
.stdout(predicate::str::contains("\"total_errors\": 0"))
.stdout(predicate::str::contains("\"name\": \"backend\""));
}
#[test]
fn workspace_check_format_markdown_emits_real_markdown_via_binary() {
Command::cargo_bin("svccat")
.unwrap()
.arg("workspace")
.arg("check")
.arg("--config")
.arg(workspace_fixture_config())
.arg("--format")
.arg("markdown")
.assert()
.success()
.stdout(predicate::str::starts_with("# Workspace Drift Report"))
.stdout(predicate::str::contains("backend"))
.stdout(predicate::str::contains("frontend"));
}
#[test]
fn workspace_check_default_terminal_format_prints_to_stdout_via_binary() {
Command::cargo_bin("svccat")
.unwrap()
.arg("workspace")
.arg("check")
.arg("--config")
.arg(workspace_fixture_config())
.assert()
.success()
.stdout(predicate::str::contains("WORKSPACE DRIFT REPORT"))
.stdout(predicate::str::contains("backend"));
}
#[test]
fn graph_format_html_renders_real_html_via_binary() {
Command::cargo_bin("svccat")
.unwrap()
.arg("graph")
.arg("--manifest")
.arg(manifest_basic_fixture())
.arg("--format")
.arg("html")
.assert()
.success()
.stdout(predicate::str::contains("<!DOCTYPE html>"))
.stdout(predicate::str::contains("svccat graph - 4 service(s)"))
.stdout(predicate::str::contains("id=\"graph-data\""));
}
#[test]
fn graph_format_html_binary_neutralizes_script_breakout_payload() {
let dir = TempDir::new().unwrap();
let root = dir.path();
std::fs::write(
root.join("services.yaml"),
r#"
discovery:
paths: ["services/*"]
services:
- name: "</script><script>alert(1)</script>"
platform: "Cloud Run"
"#,
)
.unwrap();
Command::cargo_bin("svccat")
.unwrap()
.arg("graph")
.arg("--manifest")
.arg(root.join("services.yaml"))
.arg("--format")
.arg("html")
.assert()
.success()
.stdout(predicate::str::contains("</script><script>alert").not())
.stdout(predicate::str::contains("\\u003cscript\\u003ealert(1)"));
}
#[test]
fn graph_format_mermaid_is_the_default_via_binary() {
Command::cargo_bin("svccat")
.unwrap()
.arg("graph")
.arg("--manifest")
.arg(manifest_basic_fixture())
.assert()
.success()
.stdout(predicate::str::contains("graph"));
}
#[test]
fn unknown_subcommand_exits_nonzero_via_binary() {
Command::cargo_bin("svccat")
.unwrap()
.arg("not-a-real-subcommand")
.assert()
.failure();
}