mirror of
https://github.com/l0ng-ai/tty7.git
synced 2026-09-21 16:02:20 +00:00
test(cli): walk the nested verbs when checking the reference for flags
`the_reference_documents_every_flag_of_the_verbs_it_covers` read one level: `cli.get_subcommands()`, then that verb's own arguments. Two things followed. It never descended, so every flag a level down was unchecked — `tab new --cwd`, `pane ls --all`, `pane split --ratio`, `pane close --orphans`, `server restart --hard`. And its gate for "is this verb documented" looked only for ``` `tty7 <name> ```, which the page uses for leaf verbs; a group is headed ``` ## `pane` — panes ```. So `ws`, `tab`, `pane`, `machine` and `server` were skipped whole, taking their children with them. Fifteen flags were checked where there are twenty-two. Both fixed: the walk recurses, and the gate accepts either heading shape. The reference turns out to be complete — nothing was actually undocumented, which is worth knowing rather than assuming. The matching rule was too strict as well, and the extension is what showed it: requiring a backtick immediately before the dashes reported `server restart --hard` missing when it has its own table row, written as ``` `server restart --hard` ```. It now looks for the flag anywhere on the page. The floor is five named nested flags rather than a count, because a count drifts with the surface and what has to hold is that the walk went down. Verified both ways: dropping `--orphans` from the page is reported, and stopping the recursion is reported by name.
This commit is contained in:
+69
-13
@@ -688,29 +688,85 @@ mod tests {
|
||||
// Global flags have their own table, and `--help` is clap's.
|
||||
const EVERYWHERE: [&str; 4] = ["json", "quiet", "machine", "help"];
|
||||
|
||||
// Recursive, because most of the flags are a level down: `ws rename`,
|
||||
// `pane split`, `tab close`, `machine ls`, `server restart`. Walking
|
||||
// only the top level pinned `run` and `wait` and left the rest of the
|
||||
// surface free to drift — and the reference is what an agent reads
|
||||
// before it ever runs `--help`.
|
||||
fn walk(
|
||||
cmd: &clap::Command,
|
||||
path: &str,
|
||||
doc: &str,
|
||||
everywhere: &[&str],
|
||||
missing: &mut Vec<String>,
|
||||
checked: &mut Vec<String>,
|
||||
) {
|
||||
for arg in cmd.get_arguments() {
|
||||
let Some(long) = arg.get_long() else { continue };
|
||||
if everywhere.contains(&long) {
|
||||
continue;
|
||||
}
|
||||
checked.push(format!("{path} --{long}"));
|
||||
// The flag anywhere on the page, not only at the start of a
|
||||
// code span. The page writes some of them inside a whole
|
||||
// command — ``| `server restart --hard` | …`` — and requiring
|
||||
// a backtick immediately before the dashes called that one
|
||||
// undocumented when it has its own table row.
|
||||
if !doc.contains(&format!("--{long}")) {
|
||||
missing.push(format!("{path} --{long}"));
|
||||
}
|
||||
}
|
||||
for sub in cmd.get_subcommands() {
|
||||
if sub.get_name() == "help" {
|
||||
continue;
|
||||
}
|
||||
walk(
|
||||
sub,
|
||||
&format!("{path} {}", sub.get_name()),
|
||||
doc,
|
||||
everywhere,
|
||||
missing,
|
||||
checked,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let cli = Cli::command();
|
||||
let mut missing: Vec<String> = Vec::new();
|
||||
let (mut covered, mut checked) = (0usize, 0usize);
|
||||
let mut covered = 0usize;
|
||||
let mut checked: Vec<String> = Vec::new();
|
||||
for verb in cli.get_subcommands() {
|
||||
let name = verb.get_name();
|
||||
if !DOC.contains(&format!("`tty7 {name}")) {
|
||||
// Two heading shapes, because the page uses both: a leaf verb gets
|
||||
// ``### `tty7 capture …` `` and a group gets ``## `pane` — panes``.
|
||||
// Matching only the first skipped `ws`, `tab`, `pane`, `machine`
|
||||
// and `server` — every group, and with them every nested verb.
|
||||
let documented =
|
||||
DOC.contains(&format!("`tty7 {name}")) || DOC.contains(&format!("\n## `{name}`"));
|
||||
if !documented {
|
||||
continue;
|
||||
}
|
||||
covered += 1;
|
||||
for arg in verb.get_arguments() {
|
||||
let Some(long) = arg.get_long() else { continue };
|
||||
if EVERYWHERE.contains(&long) {
|
||||
continue;
|
||||
}
|
||||
checked += 1;
|
||||
if !DOC.contains(&format!("`--{long}")) {
|
||||
missing.push(format!("{name} --{long}"));
|
||||
}
|
||||
}
|
||||
walk(verb, name, DOC, &EVERYWHERE, &mut missing, &mut checked);
|
||||
}
|
||||
// Or the loop could pass by matching nothing at all.
|
||||
assert!(covered >= 10, "only {covered} documented verbs were found");
|
||||
assert!(checked >= 5, "only {checked} verb flags were checked");
|
||||
// Named rather than counted: a count drifts with the surface, and what
|
||||
// has to hold is that the walk went a level *down*. These five live
|
||||
// under `tab`, `pane` and `server`, and a one-level walk reaches none
|
||||
// of them — which is exactly the state this test was in.
|
||||
for nested in [
|
||||
"tab new --cwd",
|
||||
"pane ls --all",
|
||||
"pane split --ratio",
|
||||
"pane close --orphans",
|
||||
"server restart --hard",
|
||||
] {
|
||||
assert!(
|
||||
checked.iter().any(|c| c == nested),
|
||||
"`{nested}` was never reached, so the walk is not descending: {checked:?}"
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
missing.is_empty(),
|
||||
"the command reference does not mention these flags: {missing:?}"
|
||||
|
||||
Reference in New Issue
Block a user