package main import ( "bytes" "context" "errors" "io" "strings" "testing" commandkit "gitea.maximumdirect.net/eric/CommandKit" ) func TestAliasesReachCoreExampleCommand(t *testing.T) { app, err := newApp() if err != nil { t.Fatal(err) } for _, test := range []struct { name string args []string entered string canonical string greeting string }{ {name: "command shortcut and scoped flag", args: []string{"hello", "--times=0", "--tag", "one"}, entered: "hello", canonical: "workspace greet", greeting: "count=explicit 0; tags=explicit [one]"}, {name: "group shortcut", args: []string{"ws", "greet", "--count=2"}, entered: "ws greet", canonical: "workspace greet", greeting: "count=explicit 2"}, {name: "canonical command", args: []string{"workspace", "greet"}, entered: "workspace greet", canonical: "workspace greet", greeting: "count=default 1 (not supplied)"}, } { t.Run(test.name, func(t *testing.T) { var output bytes.Buffer outcome := app.Execute(context.Background(), test.args, commandkit.Streams{Out: &output, Err: io.Discard}) if outcome.Kind != commandkit.OutcomeSuccess { t.Fatalf("Execute(%q) = %#v; output %q", test.args, outcome, output.String()) } for _, fragment := range []string{ test.greeting, "entered=\"" + test.entered + "\"", "canonical=\"" + test.canonical + "\"", } { if !strings.Contains(output.String(), fragment) { t.Errorf("output %q does not contain %q", output.String(), fragment) } } }) } } func TestGlobalHelpAliasDoesNotRunCoreExampleCommand(t *testing.T) { app, err := newApp() if err != nil { t.Fatal(err) } var output bytes.Buffer outcome := app.Execute(context.Background(), []string{"hello", "--hlep"}, commandkit.Streams{Out: &output, Err: io.Discard}) if outcome.Kind != commandkit.OutcomeSuccess || !strings.Contains(output.String(), "--hlep → --help") || strings.Contains(output.String(), "Hello;") { t.Fatalf("help alias outcome/output = (%#v, %q)", outcome, output.String()) } output.Reset() outcome = app.Execute(context.Background(), []string{"ws", "--help"}, commandkit.Streams{Out: &output, Err: io.Discard}) if outcome.Kind != commandkit.OutcomeSuccess || !strings.Contains(output.String(), "greet") || strings.Contains(output.String(), "Hello;") { t.Fatalf("group shortcut help outcome/output = (%#v, %q)", outcome, output.String()) } } func TestReportingExampleModes(t *testing.T) { for _, test := range []struct { name string args []string wantOutput []string wantDiag []string omitDiag []string }{ { name: "ordinary result", args: []string{"report", "demo"}, wantOutput: []string{"Prepared a local report from one fixture."}, omitDiag: []string{"Optional fixture warning", "Using deterministic local data.", "Loaded one local fixture.", "DEBUG:"}, }, { name: "progress selected", args: []string{"report", "demo", "--progress"}, wantOutput: []string{"Prepared a local report from one fixture."}, wantDiag: []string{"Loaded one local fixture."}, omitDiag: []string{"WARN:", "Using deterministic local data.", "DEBUG:"}, }, { name: "verbose messages", args: []string{"report", "demo", "--verbose"}, wantOutput: []string{"Prepared a local report from one fixture."}, wantDiag: []string{"WARN: Optional fixture warning", "The sample contains an optional note.", "Using deterministic local data.", "Summary", "Processed one local fixture."}, omitDiag: []string{"Loaded one local fixture.", "DEBUG:"}, }, { name: "debug messages", args: []string{"report", "demo", "--debug"}, wantOutput: []string{"Prepared a local report from one fixture."}, wantDiag: []string{"WARN: Optional fixture warning", "Using deterministic local data.", "Loaded one local fixture.", "DEBUG: Selected the built-in reporting example.", "Processed one local fixture."}, }, { name: "quiet suppresses result and messages", args: []string{"report", "demo", "--quiet"}, }, } { t.Run(test.name, func(t *testing.T) { outcome, output, diagnostics := executeExample(t, test.args...) if outcome.Kind != commandkit.OutcomeSuccess { t.Fatalf("Execute(%q) = %#v", test.args, outcome) } for _, fragment := range test.wantOutput { if !strings.Contains(output, fragment) { t.Errorf("output %q does not contain %q", output, fragment) } } for _, fragment := range test.wantDiag { if !strings.Contains(diagnostics, fragment) { t.Errorf("diagnostics %q does not contain %q", diagnostics, fragment) } } for _, fragment := range test.omitDiag { if strings.Contains(diagnostics, fragment) { t.Errorf("diagnostics %q unexpectedly contain %q", diagnostics, fragment) } } if test.name == "quiet suppresses result and messages" && (output != "" || diagnostics != "") { t.Errorf("quiet output/diagnostics = (%q, %q), want both empty", output, diagnostics) } }) } } func TestReportingExampleScenarios(t *testing.T) { t.Run("silent recovery retains cause", func(t *testing.T) { outcome, output, diagnostics := executeExample(t, "report", "recover") if outcome.Kind != commandkit.OutcomeSuccess || !errors.Is(outcome.Cause, errRecoveredFixture) { t.Fatalf("outcome = %#v, want successful recovery with original cause", outcome) } if output != "" || diagnostics != "" { t.Fatalf("recovery output/diagnostics = (%q, %q), want silent recovery", output, diagnostics) } }) t.Run("warning without cause", func(t *testing.T) { outcome, _, diagnostics := executeExample(t, "report", "warn", "--verbose") if outcome.Kind != commandkit.OutcomeSuccess || outcome.Cause != nil { t.Fatalf("outcome = %#v, want success without cause", outcome) } if !strings.Contains(diagnostics, "WARN: The local operation completed with a warning.") { t.Fatalf("diagnostics = %q, want explicit warning", diagnostics) } }) t.Run("warning with independent cause", func(t *testing.T) { outcome, _, diagnostics := executeExample(t, "report", "warn-error", "--verbose") if outcome.Kind != commandkit.OutcomeSuccess || !errors.Is(outcome.Cause, errWarningFixture) { t.Fatalf("outcome = %#v, want successful warning with original cause", outcome) } if !strings.Contains(diagnostics, "WARN: The local operation completed with a warning.") || strings.Contains(diagnostics, errWarningFixture.Error()) { t.Fatalf("diagnostics = %q, want warning text without cause text", diagnostics) } }) t.Run("terminal explanation without cause", func(t *testing.T) { outcome, _, diagnostics := executeExample(t, "report", "fail", "--quiet") if outcome.Kind != commandkit.OutcomeOperational || outcome.Status == 0 || outcome.Cause != nil { t.Fatalf("outcome = %#v, want terminal failure without cause", outcome) } if outcome.Explanation.Message != "The selected local operation could not be completed." || !strings.Contains(diagnostics, outcome.Explanation.Message) { t.Fatalf("explanation/diagnostics = (%q, %q)", outcome.Explanation.Message, diagnostics) } }) t.Run("partial output keeps cause independent", func(t *testing.T) { outcome, output, diagnostics := executeExample(t, "report", "partial") if outcome.Kind != commandkit.OutcomeOperational || !errors.Is(outcome.Cause, errPartialFixture) { t.Fatalf("outcome = %#v, want terminal failure with original cause", outcome) } if !strings.Contains(output, "Partial local report: first section complete.") { t.Fatalf("output = %q, want completed first section", output) } if outcome.Explanation.Message != "The local report stopped after partial output." || !strings.Contains(diagnostics, outcome.Explanation.Message) { t.Fatalf("explanation/diagnostics = (%q, %q)", outcome.Explanation.Message, diagnostics) } if strings.Contains(diagnostics, errPartialFixture.Error()) { t.Errorf("diagnostics %q unexpectedly contain cause text", diagnostics) } }) } func executeExample(t *testing.T, args ...string) (commandkit.Outcome, string, string) { t.Helper() app, err := newApp() if err != nil { t.Fatal(err) } var output, diagnostics bytes.Buffer outcome := app.Execute(context.Background(), args, commandkit.Streams{Out: &output, Err: &diagnostics}) return outcome, output.String(), diagnostics.String() }