Connect report rendering to invocation outcomes
This commit is contained in:
88
reporter_report_test.go
Normal file
88
reporter_report_test.go
Normal file
@@ -0,0 +1,88 @@
|
||||
package commandkit
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestReporterReportQuietAndClosed(t *testing.T) {
|
||||
var out bytes.Buffer
|
||||
reporter := newReporter(Streams{Out: &out})
|
||||
reporter.state.mode = modeQuiet
|
||||
err := reporter.Report(Report{Value: make(chan int)})
|
||||
if err == nil {
|
||||
t.Fatal("expected serialization error")
|
||||
}
|
||||
outcome := reporter.finalize(Success(), nil)
|
||||
if outcome.Presentation.Output.RenderError == nil || out.Len() != 0 {
|
||||
t.Fatalf("outcome %#v, output %q", outcome, &out)
|
||||
}
|
||||
if err := reporter.Report(Report{Value: "late"}); !errors.Is(err, ErrReporterClosed) {
|
||||
t.Fatalf("got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReporterReportPreservesOperationAndDeliveryEvidence(t *testing.T) {
|
||||
writeErr := errors.New("output unavailable")
|
||||
cause := errors.New("domain cause")
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
operation Outcome
|
||||
want OutcomeKind
|
||||
status int
|
||||
}{
|
||||
{"success", Success(), OutcomeOperational, 1},
|
||||
{"domain", Domain("differences", 3).WithCause(cause), OutcomeDomain, 3},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
reporter := newReporter(Streams{Out: reportErrorWriter{writeErr}})
|
||||
if err := reporter.Report(Report{Value: "result"}); !errors.Is(err, writeErr) {
|
||||
t.Fatalf("report error %v", err)
|
||||
}
|
||||
got := reporter.finalize(tc.operation, nil)
|
||||
if got.Kind != tc.want || got.Status != tc.status || !errors.Is(got.Presentation.Output.WriteError, writeErr) {
|
||||
t.Fatalf("outcome %#v", got)
|
||||
}
|
||||
if tc.name == "domain" && !errors.Is(got.Cause, cause) {
|
||||
t.Fatalf("cause %#v", got.Cause)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestReporterReportAfterCancellation(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
command := NewCommand(CommandSpec[struct{}]{Name: "run", Run: func(inv Invocation, _ struct{}) Outcome {
|
||||
cancel()
|
||||
if err := inv.Reporter().Report(Report{Value: "acquired"}); err != nil {
|
||||
t.Errorf("report: %v", err)
|
||||
}
|
||||
return Failure("canceled").WithCause(ctx.Err())
|
||||
}})
|
||||
app, err := New(Identity{Name: "Example"}, command)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var out bytes.Buffer
|
||||
result := app.Execute(ctx, []string{"run"}, Streams{Out: &out, Err: io.Discard})
|
||||
if !strings.Contains(out.String(), "acquired") || !errors.Is(result.Cause, context.Canceled) {
|
||||
t.Fatalf("outcome %#v, output %q", result, &out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReporterUsesSelectedFormat(t *testing.T) {
|
||||
var out bytes.Buffer
|
||||
reporter := newReporter(Streams{Out: &out})
|
||||
reporter.state.format = FormatJSON
|
||||
if err := reporter.Report(Report{Value: "value"}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if out.String() != "\"value\"\n" {
|
||||
t.Fatalf("got %q", &out)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user