package ckprompt import ( "bytes" "context" "errors" "io" "strings" "testing" commandkit "gitea.maximumdirect.net/eric/CommandKit" "gitea.maximumdirect.net/eric/CommandKit/integrations/ckconfig" promptkit "gitea.maximumdirect.net/eric/promptkit" ) func TestBundledNativeFailuresReachTerminalExplanation(t *testing.T) { engine := adapterEngine(t) load := func(context.Context, ckconfig.Selection, struct{}, struct{}) (*promptkit.Engine, error) { return engine, nil } for _, operation := range []string{"validation", "inspection"} { for _, mode := range []string{"ordinary", "quiet"} { t.Run(operation+"/"+mode, func(t *testing.T) { suite := FromEngine(load) suite = WithRequestValidation(suite, load, nil) var nativeErr error args := []string{"promptkit", "requirements", "validate", "briefing"} if operation == "validation" { original := suite.ValidateRequest suite.ValidateRequest = func(ctx context.Context, request ValidationRequest, input, state struct{}) (commandkit.Acquired[struct{}], error) { acquired, err := original(ctx, request, input, state) nativeErr = err acquired.Diagnostics = append(acquired.Diagnostics, commandkit.MessageDiagnostic(commandkit.SeverityWarning, "independent fixture warning")) return acquired, err } } else { args = []string{"promptkit", "show", "prompt", "missing"} original := suite.InspectPrompt suite.InspectPrompt = func(ctx context.Context, request PromptRequest, input, state struct{}) (commandkit.Acquired[*promptkit.PromptInspection], error) { acquired, err := original(ctx, request, input, state) nativeErr = err return acquired, err } } if mode == "quiet" { args = append(args, "--quiet") } var diagnostics bytes.Buffer got := newPromptTestApp(t, Command(suite)).Execute(context.Background(), args, commandkit.Streams{Out: io.Discard, Err: &diagnostics}) if nativeErr == nil { t.Fatal("fixture did not supply a native failure") } if got.Status != 1 || !errors.Is(got.Cause, nativeErr) || got.Explanation.Message != nativeErr.Error() { t.Fatalf("native error was not preserved in outcome: %#v, error=%v", got, nativeErr) } if strings.Count(diagnostics.String(), nativeErr.Error()) != 1 || strings.Contains(diagnostics.String(), "independent fixture warning") { t.Fatalf("terminal adaptation or warning visibility: %q", diagnostics.String()) } }) } } } func TestNativeOperationExplanationPreservesSuppliedContext(t *testing.T) { nativeErr := errors.New("native operation detail") for _, explanation := range []commandkit.Explanation{ {Message: "selected explanation"}, {Details: []commandkit.Detail{func(w io.Writer) error { _, err := io.WriteString(w, "native structured explanation\n"); return err }}}, } { messages := (promptKitAcquisition{explanation: explanation}).withOperationError(nativeErr) suite := Suite[struct{}, struct{}]{InspectPrompt: func(context.Context, PromptRequest, struct{}, struct{}) (commandkit.Acquired[*promptkit.PromptInspection], error) { return commandkit.Acquired[*promptkit.PromptInspection]{Explanation: messages.explanation}, nativeErr }} var diagnostics bytes.Buffer got := newPromptTestApp(t, Command(suite)).Execute(context.Background(), []string{"promptkit", "show", "prompt", "fixture", "--quiet"}, commandkit.Streams{Err: &diagnostics}) if !errors.Is(got.Cause, nativeErr) || strings.Contains(diagnostics.String(), nativeErr.Error()) || strings.Count(diagnostics.String(), "explanation") != 1 { t.Fatalf("supplied explanation was replaced or duplicated: %#v, %q", got, diagnostics.String()) } } }