fabro/lib/foundation/fabro-dev/tests/it/main.rs
2026-07-23 17:59:34 -04:00

173 lines
4.6 KiB
Rust

use std::path::{Path, PathBuf};
mod docker_build;
#[cfg(unix)]
mod docker_entrypoint;
mod docs;
mod policy;
mod release;
mod spa;
fn fabro_dev() -> assert_cmd::Command {
assert_cmd::cargo::cargo_bin_cmd!("fabro-dev")
}
pub(crate) fn workspace_root() -> PathBuf {
let mut root = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
root.pop();
root.pop();
root.pop();
root
}
fn output_text(bytes: &[u8]) -> String {
String::from_utf8(bytes.to_vec()).expect("command output should be valid utf-8")
}
#[expect(
clippy::disallowed_methods,
reason = "integration tests stage temporary fixture files with sync std::fs::write"
)]
fn write_file(root: &Path, path: &str, contents: impl AsRef<[u8]>) {
let path = root.join(path);
std::fs::create_dir_all(path.parent().expect("fixture path should have parent"))
.expect("creating fixture parent directory");
std::fs::write(path, contents).expect("writing fixture file");
}
#[expect(
clippy::disallowed_methods,
reason = "integration tests inspect fixture files with sync std::fs::read_to_string"
)]
fn read_file(root: &Path, path: &str) -> String {
std::fs::read_to_string(root.join(path)).expect("reading fixture file")
}
#[expect(
clippy::disallowed_methods,
reason = "integration tests inspect fixture files with sync std::fs::read"
)]
fn read_bytes(root: &Path, path: &str) -> Vec<u8> {
std::fs::read(root.join(path)).expect("reading fixture file")
}
#[test]
fn help_lists_scaffolded_commands() {
let output = fabro_dev()
.arg("--help")
.assert()
.success()
.get_output()
.clone();
let stdout = output_text(&output.stdout);
for command in ["build", "docker-build", "docs", "release", "spa"] {
assert!(
stdout.contains(command),
"top-level help should list {command}:\n{stdout}"
);
}
for removed_command in [
concat!("generate-cli", "-reference"),
concat!("generate-options", "-reference"),
concat!("refresh", "-spa"),
concat!("check-spa", "-budgets"),
] {
assert!(
!stdout.contains(removed_command),
"top-level help should not list removed command {removed_command}:\n{stdout}"
);
}
}
#[test]
fn group_only_spa_prints_subcommand_help_successfully() {
let output = fabro_dev()
.arg("spa")
.assert()
.success()
.get_output()
.clone();
let stdout = output_text(&output.stdout);
for command in ["refresh", "check"] {
assert!(
stdout.contains(command),
"spa help should list {command}:\n{stdout}"
);
}
}
#[test]
fn group_only_docs_prints_subcommand_help_successfully() {
let output = fabro_dev()
.arg("docs")
.assert()
.success()
.get_output()
.clone();
let stdout = output_text(&output.stdout);
for command in ["refresh", "check"] {
assert!(
stdout.contains(command),
"docs help should list {command}:\n{stdout}"
);
}
}
#[test]
fn build_help_lists_forwarded_cargo_args() {
let output = fabro_dev()
.args(["build", "--help"])
.assert()
.success()
.get_output()
.clone();
let stdout = output_text(&output.stdout);
assert!(
stdout.contains("Arguments forwarded to `cargo build`"),
"build help should explain forwarded cargo args:\n{stdout}"
);
}
#[test]
fn cargo_dev_alias_points_at_fabro_dev() {
let config = read_file(&workspace_root(), ".cargo/config.toml");
assert!(
config.contains(r#"dev = "run --package fabro-dev --features dev --""#),
"cargo dev alias should invoke fabro-dev:\n{config}"
);
}
#[test]
fn fabro_dev_does_not_depend_on_fabro_cli() {
let manifest = read_file(&workspace_root(), "lib/foundation/fabro-dev/Cargo.toml");
assert!(
!manifest.contains("fabro-cli"),
"fabro-dev should shell out to fabro-cli instead of depending on it:\n{manifest}"
);
assert!(
manifest.contains("required-features = [\"dev\"]"),
"fabro-dev binary should require the dev feature:\n{manifest}"
);
}
#[test]
fn unknown_subcommand_exits_with_clap_usage_error() {
let output = fabro_dev()
.arg("not-a-command")
.assert()
.failure()
.code(2)
.get_output()
.clone();
let stderr = output_text(&output.stderr);
assert!(
stderr.contains("unrecognized subcommand 'not-a-command'"),
"unknown subcommand should report clap usage error:\n{stderr}"
);
}