feat(cli): add help for all commands
emcli had only raw flag usage and no command listing; `--help` on agent commands even emitted a JSON error envelope and exited 2. Add real help: - Top-level `emcli` / `help` / `-h` / `--help` prints a grouped command catalogue (agent vs admin) with one-line summaries and the EMCLI_KEY/EMCLI_DB env vars. - `emcli help <command>` prints that command's synopsis + summary. - `emcli <command> --help` prints synopsis + summary + flags and exits 0. Agent commands keep stdout JSON-free (usage goes to stderr); admin commands print to stdout. Help works without EMCLI_KEY (no DB access). - help.go holds the command catalogue; flag.ErrHelp is handled as success, and admin handlers short-circuit help before opening the store. Unknown commands still error (exit 2). Full suite passes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMainHelpListsAllCommands(t *testing.T) {
|
||||
// help / --help / -h / no-args all print the command catalogue, exit 0,
|
||||
// and require no EMCLI_KEY (help must work before any DB access).
|
||||
for _, args := range [][]string{{"help"}, {"--help"}, {"-h"}, {}} {
|
||||
code, out, errOut := run(t, args...)
|
||||
text := out + errOut
|
||||
if code != 0 {
|
||||
t.Fatalf("%v: want exit 0, got %d\n%s", args, code, text)
|
||||
}
|
||||
for _, want := range []string{
|
||||
"Usage", "list", "get", "search", "ack", "send",
|
||||
"account", "whitelist", "config", "audit", "doctor", "version",
|
||||
"EMCLI_KEY", "EMCLI_DB",
|
||||
} {
|
||||
if !strings.Contains(text, want) {
|
||||
t.Fatalf("%v: help missing %q\n%s", args, want, text)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHelpForSpecificCommand(t *testing.T) {
|
||||
code, out, errOut := run(t, "help", "send")
|
||||
text := out + errOut
|
||||
if code != 0 {
|
||||
t.Fatalf("help send exit=%d", code)
|
||||
}
|
||||
if !strings.Contains(text, "Usage: emcli send") || !strings.Contains(text, "--to") {
|
||||
t.Fatalf("help send missing synopsis:\n%s", text)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAgentHelpDoesNotEmitJSON(t *testing.T) {
|
||||
// `list --help` must NOT print a JSON envelope on stdout (an agent parses
|
||||
// stdout) and must exit 0 — even with no EMCLI_KEY set.
|
||||
code, out, errOut := run(t, "list", "--help")
|
||||
if code != 0 {
|
||||
t.Fatalf("list --help exit=%d (out=%q err=%q)", code, out, errOut)
|
||||
}
|
||||
if strings.TrimSpace(out) != "" {
|
||||
t.Fatalf("agent help must keep stdout clean, got: %q", out)
|
||||
}
|
||||
if !strings.Contains(errOut, "Usage: emcli list") || !strings.Contains(errOut, "--account") {
|
||||
t.Fatalf("list --help should print usage+flags on stderr:\n%s", errOut)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSendHelpExitsZero(t *testing.T) {
|
||||
code, _, errOut := run(t, "send", "--help")
|
||||
if code != 0 || !strings.Contains(errOut, "--to") {
|
||||
t.Fatalf("send --help: code=%d err=%q", code, errOut)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAdminCommandHelpExitsZero(t *testing.T) {
|
||||
for _, c := range []string{"account", "whitelist", "config", "audit", "doctor"} {
|
||||
code, out, errOut := run(t, c, "--help")
|
||||
text := out + errOut
|
||||
if code != 0 {
|
||||
t.Fatalf("%s --help exit=%d\n%s", c, code, text)
|
||||
}
|
||||
if !strings.Contains(text, "Usage: emcli "+c) {
|
||||
t.Fatalf("%s --help missing usage line:\n%s", c, text)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user