Ctrl K
ComunidadGuías…

go/nyro_test.go

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package main

import (
	"bytes"
	"strings"
	"testing"
	"unicode/utf8"

	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
)

func TestRootCmdSubcommands(t *testing.T) {
	root := newRootCmd()
	names := map[string]bool{}
	aliases := map[string]bool{}
	for _, c := range root.Commands() {
		names[c.Name()] = true
		for _, alias := range c.Aliases {
			aliases[alias] = true
		}
	}
	if names["completion"] {
		t.Error("completion subcommand should be disabled")
	}
	if !names["tool"] {
		t.Error("tool subcommand missing")
	}
	if !names["proxy"] {
		t.Error("proxy subcommand missing")
	}
	if !names["serve"] {
		t.Error("serve subcommand missing")
	}
	if names["server"] || aliases["server"] {
		t.Error("server subcommand should have been renamed to serve without an alias")
	}
	// The pre-rename names must be fully gone: the rename ships without a
	// compatibility period, so a lingering alias would be a bug, not a courtesy.
	if names["gateway"] {
		t.Error("gateway subcommand should have been renamed to proxy")
	}
	if names["admin"] {
		t.Error("admin subcommand should have been renamed to serve")
	}
	if names["ca"] || aliases["ca"] {
		t.Error("ca must be available only under tool")
	}
	if names["migrate"] || aliases["migrate"] {
		t.Error("migrate must be available only under tool")
	}

	tool, _, err := root.Find([]string{"tool"})
	if err != nil {
		t.Fatalf("find tool command: %v", err)
	}
	toolNames := map[string]bool{}
	for _, c := range tool.Commands() {
		toolNames[c.Name()] = true
	}
	if !toolNames["ca"] {
		t.Error("tool ca subcommand missing")
	}
	if !toolNames["migrate"] {
		t.Error("tool migrate subcommand missing")
	}
}

func TestRootCmdNoGlobalStorageFlags(t *testing.T) {
	root := newRootCmd()
	if f := root.PersistentFlags().Lookup("dsn"); f != nil {
		t.Error("--dsn must not be a global/root flag (it belongs to serve only)")
	}
}

func TestRootCmdToolCommandsExecuteOnlyUnderTool(t *testing.T) {
	tests := []struct {
		name       string
		args       []string
		wantErr    bool
		wantOutput string
	}{
		{
			name:    "direct ca is rejected",
			args:    []string{"ca"},
			wantErr: true,
		},
		{
			name:    "direct migrate is rejected",
			args:    []string{"migrate"},
			wantErr: true,
		},
		{
			name:       "tool ca help resolves",
			args:       []string{"tool", "ca", "--help"},
			wantOutput: "Usage:\n  nyro tool ca",
		},
		{
			name:       "tool migrate help resolves",
			args:       []string{"tool", "migrate", "--help"},
			wantOutput: "Usage:\n  nyro tool migrate",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			root := newRootCmd()
			var output bytes.Buffer
			root.SetOut(&output)
			root.SetErr(&output)
			root.SetArgs(tt.args)
			root.SilenceUsage = true
			root.SilenceErrors = true

			err := root.Execute()
			if (err != nil) != tt.wantErr {
				t.Fatalf("Execute(%q) error = %v, wantErr %v", tt.args, err, tt.wantErr)
			}
			if tt.wantOutput != "" && !strings.Contains(output.String(), tt.wantOutput) {
				t.Errorf("Execute(%q) output = %q, want substring %q", tt.args, output.String(), tt.wantOutput)
			}
		})
	}
}

func TestPublicHelpCopyIsConcise(t *testing.T) {
	root := newRootCmd()
	var visit func(*cobra.Command)
	visit = func(cmd *cobra.Command) {
		if cmd.Hidden {
			return
		}
		if strings.Contains(cmd.Short, "`") || strings.Contains(cmd.Long, "`") {
			t.Errorf("%s command help contains backticks", cmd.CommandPath())
		}
		if utf8.RuneCountInString(cmd.Short) > 48 {
			t.Errorf("%s short help is too long: %q", cmd.CommandPath(), cmd.Short)
		}
		if cmd.Long != "" {
			t.Errorf("%s has long help; keep terminal help concise", cmd.CommandPath())
		}
		cmd.LocalNonPersistentFlags().VisitAll(func(flag *pflag.Flag) {
			usage, _, _ := strings.Cut(flag.Usage, " (env ")
			if strings.Contains(usage, "`") {
				t.Errorf("%s --%s help contains backticks", cmd.CommandPath(), flag.Name)
			}
			if utf8.RuneCountInString(usage) > 64 {
				t.Errorf("%s --%s help is too long: %q", cmd.CommandPath(), flag.Name, usage)
			}
		})
		for _, child := range cmd.Commands() {
			visit(child)
		}
	}
	visit(root)
}

func TestHelpOutputUsesConciseDescriptions(t *testing.T) {
	tests := []struct {
		args []string
		want string
	}{
		{args: []string{"--help"}, want: "serve       Start Nyro with embedded services"},
		{args: []string{"serve", "--help"}, want: "Create or update database tables on startup"},
		{args: []string{"proxy", "--help"}, want: "Token used to join config sync"},
		{args: []string{"tool", "ca", "--help"}, want: "Manage config sync certificates"},
		{args: []string{"tool", "migrate", "diff", "--help"}, want: "Writable scratch database DSN"},
	}
	for _, tt := range tests {
		root := newRootCmd()
		var output bytes.Buffer
		root.SetOut(&output)
		root.SetErr(&output)
		root.SetArgs(tt.args)
		if err := root.Execute(); err != nil {
			t.Fatalf("Execute(%q): %v", tt.args, err)
		}
		got := output.String()
		if !strings.Contains(got, tt.want) {
			t.Errorf("help for %q does not contain %q:\n%s", tt.args, tt.want, got)
		}
		for _, unwanted := range []string{
			"--auto-migrate nyro tool migrate dump",
			"--sync-listen nyro proxy",
			"--sync-token nyro proxy",
			"--sync-tls-ca nyro tool ca",
		} {
			if strings.Contains(got, unwanted) {
				t.Errorf("help for %q contains invalid placeholder %q", tt.args, unwanted)
			}
		}
	}
}