crates/cli/git-ents/tests/cli_help.rs
cli_help.rshistorycomment on this file
| 1 | //! A snapshot-style check of `git-ents --help`'s content — every |
| 2 | //! porcelain subcommand family named, with the crate's own doc as the |
| 3 | //! description. |
| 4 | //! |
| 5 | //! Not a byte-for-byte `trycmd` snapshot: `figue`'s help renderer emits |
| 6 | //! ANSI color codes unconditionally (confirmed by inspecting raw output |
| 7 | //! bytes even when redirected to a file, not a terminal), which would |
| 8 | //! make a literal snapshot fragile against `figue` version bumps rather |
| 9 | //! than against this crate's own `--help` content. Substring assertions |
| 10 | //! on the captured (ANSI-code-interspersed but still substring-intact) |
| 11 | //! output check the content that matters — every subcommand family is |
| 12 | //! named — without pinning exact styling. |
| 13 | |
| 14 | #![allow(clippy::expect_used, reason = "integration test")] |
| 15 | |
| 16 | mod common; |
| 17 | |
| 18 | use std::process::Command; |
| 19 | |
| 20 | fn help_output() -> String { |
| 21 | let output = Command::new(common::bin_path()) |
| 22 | .arg("--help") |
| 23 | .output() |
| 24 | .expect("runs"); |
| 25 | assert!(output.status.success(), "{output:?}"); |
| 26 | String::from_utf8(output.stdout).expect("utf8") |
| 27 | } |
| 28 | |
| 29 | /// Every top-level porcelain subcommand family this phase lands |
| 30 | /// (`docs/development-plan.adoc`'s phase-6 row) is named in `--help`. |
| 31 | // @relation(roots.local, scope=function, role=Verifies) |
| 32 | #[test] |
| 33 | fn help_names_every_subcommand_family() { |
| 34 | let help = help_output(); |
| 35 | for name in [ |
| 36 | "setup", |
| 37 | "members", |
| 38 | "account", |
| 39 | "effect", |
| 40 | "toolchain", |
| 41 | "comment", |
| 42 | "issue", |
| 43 | "review", |
| 44 | "inbox", |
| 45 | "redact", |
| 46 | "hook", |
| 47 | "serve", |
| 48 | "lsp", |
| 49 | ] { |
| 50 | assert!(help.contains(name), "--help must mention {name:?}:\n{help}"); |
| 51 | } |
| 52 | } |
| 53 | |
| 54 | /// `git ents lsp --help` documents the stdio-only, no-socket, |
| 55 | /// no-git-transport contract `lens.serve` requires, not just a bare flag |
| 56 | /// list. |
| 57 | #[test] |
| 58 | // @relation(lens.serve, scope=function, role=Verifies) |
| 59 | fn lsp_help_documents_the_stdio_only_contract() { |
| 60 | let output = Command::new(common::bin_path()) |
| 61 | .args(["lsp", "--help"]) |
| 62 | .output() |
| 63 | .expect("runs"); |
| 64 | assert!(output.status.success(), "{output:?}"); |
| 65 | let text = String::from_utf8(output.stdout).expect("utf8"); |
| 66 | assert!(text.contains("stdio") || text.contains("stdin"), "{text}"); |
| 67 | assert!(text.contains("socket"), "{text}"); |
| 68 | } |
| 69 | |
| 70 | /// `--help` carries this crate's own one-line responsibility, not a |
| 71 | /// generic placeholder. |
| 72 | #[test] |
| 73 | fn help_carries_the_crate_doc() { |
| 74 | let help = help_output(); |
| 75 | assert!(help.contains("Local root wiring"), "{help}"); |
| 76 | } |
| 77 | |
| 78 | /// A subcommand's own `--help` (e.g. `members --help`) also renders, |
| 79 | /// confirming the nested subcommand grammar is reachable, not just the |
| 80 | /// top level. |
| 81 | #[test] |
| 82 | fn nested_help_reaches_a_subcommand() { |
| 83 | let output = Command::new(common::bin_path()) |
| 84 | .args(["members", "--help"]) |
| 85 | .output() |
| 86 | .expect("runs"); |
| 87 | assert!(output.status.success(), "{output:?}"); |
| 88 | let text = String::from_utf8(output.stdout).expect("utf8"); |
| 89 | assert!(text.contains("list"), "{text}"); |
| 90 | assert!(text.contains("revoke"), "{text}"); |
| 91 | } |
| 92 | |
| 93 | /// `git ents serve --help` documents the loopback-only, no-git-transport |
| 94 | /// contract `roots.local` requires, not just a bare flag list. |
| 95 | #[test] |
| 96 | // @relation(roots.local, scope=function, role=Verifies) |
| 97 | fn serve_help_documents_the_loopback_only_contract() { |
| 98 | let output = Command::new(common::bin_path()) |
| 99 | .args(["serve", "--help"]) |
| 100 | .output() |
| 101 | .expect("runs"); |
| 102 | assert!(output.status.success(), "{output:?}"); |
| 103 | let text = String::from_utf8(output.stdout).expect("utf8"); |
| 104 | assert!(text.contains("loopback"), "{text}"); |
| 105 | assert!(text.contains("port"), "{text}"); |
| 106 | } |