Files
summercms/modules/diary/helponly_test.go
Jakub Zych 6c606c666b feat(diary): boot list, help and completion requests quietly (quick-261028-rqc)
- helpOnly also counts no command word, list, help, cobra's shell
  completion requests and --help=<bool>, read the way pflag does
- TestHelpOnlyAgreesWithCobra pins the classification against bonfire's
  real dispatch, with the passthrough --help case as the exception
- console and logging docs describe which invocations boot quietly
2026-10-28 21:47:42 +01:00

134 lines
4.8 KiB
Go

package diary_test
import (
"context"
"io"
"strings"
"testing"
"github.com/spf13/cobra"
"git.golem15.com/golem15/summercms/modules/bonfire"
"git.golem15.com/golem15/summercms/modules/diary"
)
// helpOnlyCases are the rows shared by TestHelpOnly and
// TestHelpOnlyAgreesWithCobra. usage marks the rows cobra rejects as a
// usage error, which the agreement check leaves out.
var helpOnlyCases = []struct {
args []string
want bool
usage bool
}{
{args: []string{}, want: true},
{args: []string{"--help"}, want: true},
{args: []string{"-h"}, want: true},
{args: []string{"serve", "--help"}, want: true},
{args: []string{"serve", "-h"}, want: true},
{args: []string{"-h", "serve"}, want: true},
{args: []string{"serve", "--help=true"}, want: true},
{args: []string{"serve", "--help=1"}, want: true},
{args: []string{"-nh", "serve"}, want: true},
{args: []string{"-vh", "serve"}, want: true},
{args: []string{"serve", "-vh=true"}, want: true},
{args: []string{"list"}, want: true},
{args: []string{"list", "--format=json"}, want: true},
{args: []string{"help"}, want: true},
{args: []string{"help", "serve"}, want: true},
{args: []string{"--env", "staging"}, want: true},
{args: []string{"--env=staging"}, want: true},
{args: []string{"-v"}, want: true},
{args: []string{"--help=false"}, want: true},
{args: []string{"--env", "help"}, want: true},
{args: []string{"__complete", "serve", ""}, want: true},
{args: []string{"__completeNoDesc", "se"}, want: true},
{args: []string{"serve"}},
{args: []string{"migrate", "-v"}},
{args: []string{"queue:work"}},
{args: []string{"--env", "list", "serve"}},
{args: []string{"serve", "--", "--help"}},
{args: []string{"serve", "--help=false"}},
{args: []string{"serve", "--help", "--help=false"}},
{args: []string{"serve", "-h=false"}},
{args: []string{"serve", "-qv"}},
{args: []string{"serve", "-xh"}, usage: true},
{args: []string{"serve", "--help=yes"}, usage: true},
{args: []string{"blog:import", "https://example.com/help"}},
{args: []string{"blog:import", "help"}},
{args: []string{"-q", "--env=list", "migrate"}},
}
func TestHelpOnly(t *testing.T) {
for _, tc := range helpOnlyCases {
if got := diary.HelpOnly(tc.args); got != tc.want {
t.Errorf("helpOnly(%q) = %v, want %v", tc.args, got, tc.want)
}
}
}
// helpOnlyRoot builds a root whose commands record whether their Run ran.
func helpOnlyRoot(t *testing.T, ran *bool) *cobra.Command {
t.Helper()
run := func(context.Context, bonfire.Input, bonfire.Output) error {
*ran = true
return nil
}
optional := []bonfire.Arg{{Name: "target", Description: "An optional argument"}}
commands := []bonfire.Command{
{Name: "serve", Description: "Start the HTTP server", Args: optional, Run: run},
{Name: "migrate", Description: "Run the migrations", Run: run},
{Name: "queue:work", Description: "Run the job workers", Run: run},
{Name: "blog:import", Description: "Import posts", Args: optional, Run: run},
{Name: "acme:tool", Description: "Run a tool with its own flags", Passthrough: true, Run: run},
}
root, err := bonfire.NewRootIO("acme", commands, strings.NewReader(""), io.Discard, io.Discard,
bonfire.WithVersion(bonfire.Version{App: "v1.0.0", Framework: "v1.0.0"}))
if err != nil {
t.Fatal(err)
}
return root
}
// TestHelpOnlyAgreesWithCobra: for every row cobra accepts, a command runs
// exactly when helpOnly reports false. A passthrough command is the
// documented exception: its --help reaches its Run, while helpOnly, which
// cannot know the command before boot, counts it.
func TestHelpOnlyAgreesWithCobra(t *testing.T) {
for _, tc := range helpOnlyCases {
var ran bool
code := bonfire.Execute(context.Background(), helpOnlyRoot(t, &ran), tc.args)
if tc.usage {
if code != bonfire.ExitUsage {
t.Errorf("Execute(%q) = %d, want the usage error %d", tc.args, code, bonfire.ExitUsage)
}
continue
}
if code != bonfire.ExitOK {
t.Errorf("Execute(%q) = %d, want 0", tc.args, code)
continue
}
if ran != !diary.HelpOnly(tc.args) {
t.Errorf("Execute(%q) ran a command = %v, but helpOnly = %v", tc.args, ran, diary.HelpOnly(tc.args))
}
}
t.Run("passthrough --help", func(t *testing.T) {
args := []string{"acme:tool", "--help"}
var ran bool
if code := bonfire.Execute(context.Background(), helpOnlyRoot(t, &ran), args); code != bonfire.ExitOK {
t.Fatalf("Execute(%q) = %d, want 0", args, code)
}
if !ran || !diary.HelpOnly(args) {
t.Errorf("Execute(%q) ran = %v, helpOnly = %v; want both true (the documented exception)", args, ran, diary.HelpOnly(args))
}
})
if diary.CompleteRequestCmd != cobra.ShellCompRequestCmd {
t.Errorf("completion command %q, cobra uses %q", diary.CompleteRequestCmd, cobra.ShellCompRequestCmd)
}
if diary.CompleteNoDescRequestCmd != cobra.ShellCompNoDescRequestCmd {
t.Errorf("completion command %q, cobra uses %q", diary.CompleteNoDescRequestCmd, cobra.ShellCompNoDescRequestCmd)
}
}